我一直在使用DUnit作为TDD的驱动程序在Delphi 5中开发一些软件但我发现在使用CheckEqualsMem时它仍然失败,即使在调试器中我可以看到被比较的对象(在这种情况下是两个长字的数组)相同.
在内部,CheckEqualsMem使用CompareMem,发现这是返回false的内容.
深入研究我发现,如果我使用@或Addr调用CompareMem指向对象地址的指针,即使内存相同,CompareMem也会失败,但如果我使用PByte(来自windows)或PChar,它会正确地比较内存.
为什么?
这是一个例子
var
s1 : String;
s2 : String;
begin
s1 := 'test';
s2 := 'tesx';
// This correctly compares the first byte and does not return false
// since both strings have in their first position
if CompareMem(PByte(s1), PByte(s2), 1) = False then
Assert(False, 'Memory not equal');
// This however fails ?? What I think I am doing is passing a pointer
// to the address of the memory where the variable is and telling CompareMem
// to compare the first byte, but I must be misunderstanding something
if CompareMem(@s1,@s2,1) = False then
Assert(False,'Memory not equal');
// Using this syntax correctly fails when the objects are different in memory
// in this case the 4th byte is not equal between the strings and CompareMem
// now correctly fails
if CompareMem(PByte(s1),PByte(s2),4) = False then
Assert(False, 'Memory not equal');
end;
Run Code Online (Sandbox Code Playgroud)
正如你在评论中看到的那样,我来自C背景,所以我认为@ s1是指向s1的第一个字节的指针而PByte(s1)应该是同一个东西,但它不是.
我在这里误解了什么?@/Addr和PByte有什么区别?
不同的是,@s1是地址可变的s1而PBYTE(S1)是值的可变的s1.
内部的字符串变量是指向字符串数据@s1的指针,因此是指向指针的指针.这条线
CompareMem(@s1,@s2,1);
Run Code Online (Sandbox Code Playgroud)
比较地址s1和s2字符串的两个最低有效字节; 它没有任何意义,没有关系由引用的字符串数据Pointer(s1)和Pointer(s2).