我得到这个错误将调试项目,该项目使用的是在Delphi 7,我已经升级到德尔福XE2,在几种方法发生了同样的错误。
First chance exception at $006DC660. Exception class $C0000005 with message 'access violation at 0x006dc660 read of address 0xffffffff'
这是方法之一:
PFI = ^TFI;
TFI = record
Id : TToken;
Name : TName;
Parameters : string;
end;
function TListFI.IsIn(S: PChar): PFI;
function SearchName2(Item: PFI):Boolean;
var N1, N2: PChar;
begin
N1:= StrNew(Item^.Name);
N2:= StrNew(S); //Here is the issue
SearchName2:= (StrComp(StrUpper(N1), StrUpper(N2)) = 0);
StrDispose(N1);
StrDispose(N2);
end;
begin
IsIn:= PFI(FirstThat(@SearchName2));
end;
我用Google搜索,我发现有人描述了类似的问题,他肯定的是,当增量链接被禁用它的工作原理,可有人告诉我什么,它在哪里或者给一些建议来解决这种情况。
[编辑]
现在卸下@给我下面的错误ISIN:= PFI(FirstThat(SearchName2));
E2010 Incompatible types: 'TObject' and 'PFI'
我加入FirstThat程序,看它是否可能帮助。
TFuncionColeccion = function (Elemento: TObject): Boolean;
function TColeccion.FirstThat (Rutina: TFuncionColeccion): TObject;
var
i: Integer;
begin
For i:=0 to Count-1 do
if Rutina(Items[i]) then
begin
FirstThat:=Items[i];
exit;
end;
FirstThat:=nil;
end;
这是(而且一直)通过指针调用本地(嵌套)程序,这是你清楚什么错误FirstThat
功能一样。 编译器有做特别的事情与堆栈调用本地函数,并给他们访问父范围的变量( S
在你的代码),但是编译器只知道做那些特别的东西当本地函数直接调用。 编译器无法知道参数FirstThat
将是一个局部功能,因此它不包括特殊代码时FirstThat
调用指向的作用。
底线是,在函数内部堆栈不被设置了它应该的方式,这意味着可能出现任何数量的奇怪症状。 你必须使用一些其他的方式。 也许让SearchName2
是两个参数的函数,然后写FirstThat
接受S
因为它可以转发到函数参数的参数。
你不应该需要使用@
构造函数指针时操作。 当你这样做时,编译器倾向于跳过类型检查,这是什么让你通过本地函数指针FirstThat
摆在首位。 当你真的传递函数所需的原型相匹配,编译器将允许您通过它没有@
操作。
您报告中的访问冲突
StrNew(S)
其中S
的类型为PChar
。 的解释为,与概率非常接近1,是S
事实上不是一个指向空的终止阵列WideChar
。
在Delphi 7, PChar
是一个别名PAnsiChar
。 也就是说为null的终止阵列的指针AnsiChar
,即8位的字符。 在Delphi XE2, PChar
是别名PWideChar
,指针为null的终止阵列WideChar
,即16个字符。
它有助于了解StrNew
一样。 它引导的阵列,直到它找到一个空字符。 对于8位文本是一个零字节。 对于16位的文字,零是零16位字。 然后它分配的相同的长度的输入字符串的存储一个新的块,并进行复印到新的存储器。 的源代码是:
function StrNew(const Str: PWideChar): PWideChar;
var
Size: Cardinal;
begin
if Str = nil then Result := nil else
begin
Size := StrLen(Str) + 1;
Result := StrMove(WideStrAlloc(Size), Str, Size);
end;
end;
唯一可行的失效模式是,当StrLen
行走阵列,它尝试一个无效存储器读。 如果你输入的参数是无效的,只能发生。 换句话说,这一定是你一个编程错误。
一个可能的解释是,你实际上是通过8位文本这个功能虽然承诺通过16位的文本。 一个容易犯的错误,特别是如果你还没有完全熟悉Unicode的变化。 8位文本具有零终止,但后面的字节碰巧不为零。 或零字节落在奇数从一开始偏移。 然后StrNew
继续走缓冲区,但现在它是关闭的结束,所以发生,它并没有超越到尚未分配的地址之前找到一个零字。 这是一个访问冲突。
如果是这样的话解决方案将是两种:
- 更改函数的参数为类型
PAnsiChar
,并固定在调用点半信半疑的铸造。 - 通过该功能16位文本,因为它需要。
在你更新你包括不能被读取的地址, 0xffffffff
。 这是-1
十六进制。 这似乎是最平淡无奇的错误。 您的指针完全是假的! 你确切的错误信息可使用此代码被复制: StrNew(PChar(-1))
我没有在这里足够的信息来告诉你为什么你的指针是伪造的。 希望你学到一些调试和诊断技术,使您解决问题。 至少你现在知道错误是在你的代码。
假设BuscaName2和SearchName2是同一个东西,那么你需要看没有进一步。 当地的程序只能从包含函数调用。 作为@Rob正确地说,用程序使用@几乎总是不正确的,是严重的问题与您的代码的警告信号。