gpt4 book ai didi

在记录类型之间分配字符串时出现 Delphi 访问冲突错误

转载 作者:行者123 更新时间:2023-12-03 15:03:14 25 4
gpt4 key购买 nike

我有一个简单的记录类型。我分配该记录的一个新实例,并使用过程(“_clone”)将值从现有记录复制到新记录。仅当分配字符串值时,我才会遇到访问冲突。

有什么想法吗?非常感谢您的帮助。

<小时/>

类型定义:

TPointer = ^TAccessoryItem;
TAccessoryItem = Record
Id : Integer;
PartNumber : String;
Qty : Integer;
Description : String;
Previous : Pointer;
Next : Pointer;
end;
<小时/>
Procedure TAccessoryList._clone (Var copy : TAccessoryItem; Var original : TAccessoryItem);

begin

copy.Id := original.Id;
copy.Qty := original.Qty;
copy.Partnumber := original.Partnumber; **// Access errors happens here**
copy.Next := Nil;
copy.Previous := Nil;

end;
<小时/>

调用下面的应用程序:

  procedure TAccessoryList.AddItem(Var Item : TAccessoryItem);

Var

newItem : ptrAccessoryItem;

begin

GetMem(newItem, sizeOf(TAccessoryItem));

_clone(newItem^, Item);

end;

最佳答案

您需要用零初始化新结构。 GetMem 不会将分配的内存清零,因此记录的字段最初包含随机垃圾。您需要调用

FillChar(newItem^, sizeof(TAccessoryItem), 0)

在 GetMem 之后、使用记录之前。

原因如下:当您分配给新分配但未初始化的记录的字符串字段时,RTL 会发现目标字符串字段不为空(包含垃圾指针),并尝试取消引用该字符串以减少其之前的引用计数将新的字符串值分配给该字段。这对于每次对字符串字段或变量的赋值都是必要的,以便在将新值分配给字符串字段或变量之前,如果没有其他字符串使用它,则将释放前一个字符串值。

由于指针是垃圾,因此您会遇到访问冲突...如果您幸运的话。随机垃圾指针可能恰好是指向进程中分配的地址范围的值。如果发生这种情况,您将不会在赋值时获得 AV,但在程序执行后期可能会遇到更糟糕、更神秘的崩溃,因为对未初始化变量的字符串赋值已经改变了进程中其他地方的内存不恰当。

每当您直接处理内存指针并且您分配的类型包含编译器托管字段时,您都需要非常小心地初始化和处置该类型,以便正确初始化和处置编译器托管字段。

在 Delphi 中分配记录的最佳方法是使用 New() 函数:

New(newItem);

编译器将从指针的类型推断分配大小(指针类型指向的大小),分配内存,并为您适本地初始化所有字段。

对应的释放器是Dispose()函数:

Dispose(newItem);

除了释放记录本身使用的内存之外,这将确保正确处理记录的所有编译器管理的字段。

如果您只是 FreeMem(newItem),则会泄漏内存,因为该记录中的字符串和其他编译器管理的字段占用的内存将不会被释放。

编译器管理的类型包括长字符串(“String”,而不是“string[10]”)、宽字符串、变体、接口(interface),以及可能我已经忘记的东西。

一种思考方式是:GetMem/FreeMem 只是分配和释放内存块。他们对如何使用该 block 一无所知。不过,New 和 Dispose 会“了解”您为其分配或释放内存的类型,因此它们将执行任何额外的工作以确保自动处理所有内部事务。

一般来说,最好避免使用 GetMem/FreeMem,除非您真正需要的只是一 block 没有与之关联的类型语义的原始内存块。

关于在记录类型之间分配字符串时出现 Delphi 访问冲突错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5128813/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com