我不太确定如何提出这个问题,因为我不知道它是否与执行时间,申请流程,消息程序或其他任何内容有关。
我(对我来说)奇怪的情况,程序无法运行并在运行时引发系统异常,而如果我把" showmessage"它运行完全完美无瑕。介于两者之间(我把它放在一起,以便我可以很快看到它们之间发生了什么。我更喜欢这种方式而不是以某种方式......)。
我不确定代码是否重要,但我会在下面给出:
procedure LoadSettings;
var SettingsBuffToLoad: TStringList;
begin
SettingsBuffToLoad:=TStringList.Create;
Encoding:=TEncoding.ANSI;
SettingsBuffToLoad.LoadFromFile('bin/settings.txt', Encoding);
// showmessage(settingsbufftoload.Strings[0]);
SettingsBuffer:=Decode(SettingsBuffToLoad);
// showmessage(settingsbuffer.Strings[0]); //decode
end;
解码过程被声明为外部,并从dll中读取。
如果我删除那些" /" ,它使它成为代码而不是评论,它的工作正常。但是,按照您现在的设置,它会引发异常,但在该过程已经完成之后。 (调试器的最后一个断点在" end;"停止,然后继续它会引发异常而不是显示表单;这个过程被称为FormCreate过程中的最后一个。
有什么与时间有关,ShowMessage解决了,还是......? :/
更新: 解码函数,问:
这就是它的实现方式,正好在表单的实现和变量之上:
function Decode(Buff:TStringList):TStringList; STDCALL; external' bin \ settings.txt';
这是在dll中:
function Decode(Buff: TStringList): TStringList; export;
var
t, u, h: integer;
s: String;
begin
DecodeBuffer.Clear;
DecodeBuffer:=Buff;
for h := 0 to DecodeBuffer.Count-1 do
begin
s := DecodeBuffer.Strings[h];
t := Length(s);
if t > 0 then
begin
for u := 0 to t-1 do
begin
s[u+1] := DecodeChar(s[u+1], (h mod 5) + 1);
end;
DecodeBuffer.Strings[h] := s;
end;
end;
Result:=DecodeBuffer;
end;
此代码在Delphi changing Chars in string - missunderstood behavior - XE3的问题中进行了讨论,并在Remy的答案中使用。 DecodeChar,我相信在这里根本不重要,或者是它?
此外,保存设置的功能也是如此,在FormClose事件中调用:
这是:
procedure TScribbles.SaveSettings;
var SettingsBuffToSave: TStringList;
begin
SettingsBuffToSave:=TStringList.Create;
Encoding := TEncoding.ANSI;
// Showmessage(settingsbuffer.Strings[0]);
SettingsBuffToSave:=Encode(SettingsBuffer);
// Showmessage(settingsbufftosave.Strings[0]);
SettingsBuffToSave.SaveToFile('bin/settings.txt', Encoding);
end;
第一个ShowMessage用作代码而不是注释,它可以工作,而在上面写的注释函数中,它以与Decode相同的方式调用外部异常。 是否有可能,当它已经调用函数Encode时,尚未创建SettingsBuffToSave,或者是什么? 那时,SettingsBuffer存在并被填充,所以它引发错误似乎很奇怪,只需将ShowMessage放在那里就会消失。
(函数编码基本上是解码的镜像,所以代码在这里并不重要......)
答案 0 :(得分:3)
这段代码在很多层面都非常危险。以不安全的方式跨DLL边界使用对象。跨函数调用的对象指针管理不善。你需要重新设计。尝试以下作为开始:
procedure Decode(Buff: PChar; BuffLen: Integer; ListIndex: Integer); stdcall; export;
var
u: integer;
begin
for u := 0 to BuffLen-1 do
begin
Buff^ := DecodeChar(Buff^, (ListIndex mod 5) + 1);
Inc(Buff);
end;
end;
procedure Encode(Buff: PChar; BuffLen: Integer; ListIndex: Integer); stdcall; export;
var
u: integer;
begin
for u := 0 to BuffLen-1 do
begin
Buff^ := EncodeChar(Buff^, (ListIndex mod 5) + 1);
Inc(Buff);
end;
end;
procedure Decode(Buff: PChar; BuffLen: Integer; ListIndex: Integer); stdcall; external '...';
procedure Encode(Buff: PChar; BuffLen: Integer; ListIndex: Integer); stdcall; external '...';
procedure LoadSettings;
var
h: Integer;
begin
SettingsBuffer := TStringList.Create;
SettingsBuffer.LoadFromFile('bin/settings.txt', TEncoding.ANSI);
for h := 0 to SettingsBuff.Count-1 do
begin
Decode(PChar(SettingsBuff[h]), Length(SettingsBuff[h]), h);
end;
end;
procedure TScribbles.SaveSettings;
var
h: Integer;
begin
for h := 0 to SettingsBuff.Count-1 do
begin
Encode(PChar(SettingsBuff[h]), Length(SettingsBuff[h]), h);
end;
SettingsBuff.SaveToFile('bin/setpb95enc.dll', TEncoding.ANSI);
end;
答案 1 :(得分:1)
这里显而易见的问题是代码存在于DLL中。很可能你没有安排DLL共享它的主机堆。并且Delphi类不能跨DLL边界传递。
如果要在模块之间共享Delphi类,则必须使用包。当然,另一种选择是将所有代码放在同一个模块中。那就是删除DLL,并编译可执行文件中的所有内容。最后一个选项是为DLL使用有效的互操作类型。
当然,实际错误可能还有其他原因。代码闻起来很糟糕。例如,这是什么:
DecodeBuffer:=Buff;
DecodeBuffer
是全局变量吗?如果是这样,那么在物体被摧毁后引用它是合理的。并不是说我能看到任何被破坏的证据。不希望看起来粗鲁,你的代码看起来可能有多个问题。作为紧急事项,您需要:
答案 2 :(得分:0)
我想我知道这里发生了什么:我认为你的筹码正在被粉碎。
此外,我更怀疑实际原因是使用未初始化变量的Decode过程。你的ShowMessage语句(如果我正确的话,它将是第一个重要的)改变堆栈上的内容,从而改变未初始化的变量。
如果我说得对,这会产生一些heisenbug属性 - 你所做的任何事情都会改变未初始化变量的值。
要尝试的一件事:声明一个大的局部变量(想法是用尽堆栈空间)并确保它不会被编译器丢弃。这将把事情转移到记忆中,从而可能化解爆炸。如果它起作用,它对于正在发生的事情非常有把握。