我有这个令人讨厌的虫子在过去消失了,但现在经过一段时间它又回来了.
我有两个TSam对象(派生自TPersistent)创建并加载到TAsmJob对象(从TObjectList派生).
在运行时,表单创建一个TStringGrid,然后创建AsmJob,它创建这两个SAM对象(并从每个对象的磁盘加载一些数据).AsmJob也被分配给网格.当表单被销毁时,Grid通过释放它来处理AsmJob,从而释放TSam对象.这是问题所在:第一个对象没有问题,但第二个对象在调用其继承方法(在Destroy析构函数中)时会死掉.
我在整个程序中使用FreeAndNil来释放对象.TSam对象不是NIL !!!!! 所以,这是第一次释放对象的尝试.甚至对象内部的数据也是一致的.
该计划的主干如下:
**Create:**
Form -> StringGrid
-> AsmJob -> Sam1, Sam2
StringGrid.AsmJob:= AsmJob;
**Free:**
Form -> StringGrid -> AsmJob -> Sam1, Sam2
Run Code Online (Sandbox Code Playgroud)
我真的不明白在它被释放后我试图双重释放或覆盖对象的位置.
编辑:
我得到的一些错误:
FastMM在空闲块扫描操作期间检测到错误.FastMM在释放后检测到块已被修改.
FastMM在空闲块扫描操作期间检测到错误.块头已损坏.
详情:
The current thread ID is 0x19C, and the stack trace (return addresses) leading to this error is:
402E77 [System][@FreeMem]
4068DC [System][@DynArrayClear]
405E2D [System][@FinalizeArray]
405D31 [System][@FinalizeRecord]
40432F [System][TObject.CleanupInstance]
404272 [System][TObject.FreeInstance]
404641 [System][@ClassDestroy]
4D313E [UnitSam.pas][TSam.Destroy][297]
4042BF [System][TObject.Free]
4149ED [SysUtils][FreeAndNil]
4D9C0A [UnitAsmJob.pas][UnitAsmJob][TAsmJob.Destroy][180]
Run Code Online (Sandbox Code Playgroud)
我在IDE中启用了所有"调试"选项,包括"范围检查".此外,FastMM4设置为超级激进的调试模式.如果没有FastMM或者在调试器之外,程序运行得很好 - 但我知道这并不意味着错误不再存在.实际上它(可能)工作了一年多,直到我安装了FastMM.
编辑:
感谢大家.不,我感觉我正朝着好的方向前进.
程序的结构更复杂我只提供了保持原始帖子小的骨干.但是,它已经变大了:)所以,那些TSam对象用于从磁盘加载数据.每个对象中有一个文件.他们还在进行一些处理和数据验证.对于这些TSam中的每一个,我还有一个图形对象,在屏幕上(图形地)显示TSam对象中包含的数据.TStringGrid中的每一行也以TSam显示数据,但是以文本方式显示.
我有一个问题:如果我以较小的碎片打破程序以找出错误的位置,错误仍会出现?或者只能在此特定配置中出现?
回答"如何将AsmJob分配给TStringGrid,以便TStringGrid破坏AsmJob,你能告诉我们吗?" …
我有一个类,我们称之为TMyObject,它应该返回一个稍微修改过的自身副本.因此,它的一个函数应该返回一个与它自身相同类型的对象:
function TMyObject.TrimEnds: TMyObject;
begin
Result:= TMyObject.Create;
Result.DoStuff;
edn;
Run Code Online (Sandbox Code Playgroud)
我能这样做吗?这是合法的我在做什么?
我的意思是,我已经尝试过了,编译器允许我这样做,但我想知道是否会有很长时间/隐藏的负面影响.
任何想法将不胜感激.谢谢.
编辑:新略微修改的副本将保存到磁盘.这是某种"拯救......".工作原理:原始对象创建自身的副本,指示此副本进行一些更改并保存到磁盘.然后原来释放副本.这样我保持原始对象在内存中不变,但我有一个修改版本的磁盘.
您可能认为我的对象有图片.我需要的是一个函数,它返回一个稍微修改过的图片副本.
我需要找到TScrollBox的整个大小(也称为"逻辑区域") - 与通过Width和Height属性(或ClientWidth ClientHeight)获得的可见区域相反.
我想在TScrollBox中创建一些控件.其中一个(称为TViewer)需要与TScrollBox本身一样高.问题是在创建过程中,TScrollBox向下滚动以显示上次创建的控件.因此,使用Top = 1将不起作用,因为我的控件将具有top = 1,这不是逻辑区域的顶部.
德尔福7
在最近的帖子中(我的程序永远不会释放内存.为什么?)我表明在使用FastMM时,应用程序不会释放大量内存回系统.最近我创建了一个人工测试程序,以确保它不是一个内存的问题,它只出现在FastMM中.
在这个程序中,我创建并销毁一个对象(与前一篇文章中使用的对象相同)500次.
内存要求是("私人工作集"):
没有FastMM
在运行循环之前:1.2MB
运行循环后:2.1MB
使用FastMM(激进的调试模式)
在运行循环之前:2.1MB
运行循环后:25MB
使用FastMM(发布模式)
运行循环之前:1.8MB
运行循环后:3MB
如果我多次运行循环,则内存要求不会增加.这意味着重用未释放的内存,因此这不是内存泄漏(内存泄漏会增加内存占用,每次运行时会有几KB/MB).
我的问题是:
如何在FastMM中禁用此行为?它甚至可能吗?我知道,如果我在没有FastMM或FastMM Release Mode的情况下发布程序,它将"浪费"适量的RAM.但是,根据需要禁用此行为,将帮助我(我们?)识别内存泄漏.实际上在我的第一篇文章中(见链接),很多人都认为我有泄漏.由于这种行为,显然造成了混乱.不,很明显没有泄漏.只是内存管理器拒绝释放大量内存.
它会释放额外的内存吗?什么时候?什么引发了这个?程序员可以触发吗?例如,当我知道我已经完成了RAM密集型任务并且用户可能暂时不使用该程序(最小化它)时,我可以将RAM刷回系统吗?当用户打开我的程序的多个实例时会发生什么?他们不会争夺内存吗?
我想让用户创建同一表单的多个实例(让我们称之为Form1,这是一个MDI子表单).所以我有两个这样的程序,我创建表单.
procedure MyProcedure1; // procedure 2 is similar. it also has a var called MyFrm
var MyFrm: TFrm1;
begin
...
MyFrm:= TFrm1.create(MainForm);
MyFrm.BringToFront;
MyFrm.LoadFromFile(someFile);
end;
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,MyFrm是本地变量.这对我来说没问题,因为我创建它之后不需要以编程方式访问表单.没有其他名为Frm1的全局变量.在MyFrm的OnClose事件中,我有Action:= caFree;
什么可能导致上述错误?用户发送了该错误.它只发生一次,我无法重现它.
编辑:
该错误出现在"MyFrm:= TFrm1.create"行中.
有些人建议我需要以编程方式为动态创建的表单指定唯一的名称.我也想知道自己在创建表单时所采用的名称,因此我在调用MyProcedure1过程时进入了代码.
Delphi自动提供唯一的名称,如
MyFrm.name = MyFrm,然后是
MyFrm.name = MyFrm_1,
MyFrm.name = MyFrm_2,
MyFrm.name = MyFrm_3,依此类推.
LoadFromFile中未更改MyFrm.Name.我在程序MyProcedure1的末尾检查了(断点)'MyFrm.Name'的值; 在LoadFromFile之后.这个名字很独特.
正如一些人建议的那样,我重写了SetName过程并检查了TMyFrm的名称.确实,每个表格都有一个独特的名称
procedure TMyFrm.SetName(const Value:TComponentName);
开始
ShowMessage(Value);
遗传;
结束;
我在这个应用程序中有许多表单,但只有MainForm是自动创建的.
我不使用线程.无论如何,这是不相关的,因为表单是由用户创建的(因此多线程是无关紧要的,除非用户可以同时创建2个表单).
我需要将一些数据存储在一个文件中.每个记录(数据集)包括:
将所有这些东西保存在二进制文件中并不困难.但是,我确信(不幸的是)我的数据格式会随时间发生变化,我希望有可能为每个"记录"添加更多字段.所以,显然我的文件格式无法修复.我想最好的解决方案是将数据保存在(DB)表中,但我不想搞砸大枪(SQL,ADO,BDE,Nexus ......).我需要一个可以做到这一点的基础库(如果可能的话,单个PAS文件).由于这样做的目的是存储数据而不是处理数据,是否可以在没有DB表的情况下完成?
该库的要求:
我用的是D7
在安装Delphi XE后,我的旧版Delphi 7开始更频繁地崩溃.今天,我发现我的一个BPL仍然被D7加载,即使我从"c:\ Program Files\Borland\Delphi7\Projects\Bpl"中删除了它.在搜索完整个磁盘后,我在"c:\ Users\Public\Documents\RAD Studio\8.0\Bpl"中发现了该BPL的副本.
我的问题是:为什么Delphi 7会查看"c:\ Users\Public\Documents\RAD Studio\8.0\Bpl"?我怎么能说服它只查看"c:\ Program Files\Borland\Delphi7\Projects\Bpl"?
我尝试在imgQInput(这是一个TImage)中加载图像,将其分配给TJpegImage,压缩它(压缩因子5)并在imgQOutput(另一个TImage)中显示它.但它不起作用.imgQOutput中的图像与原始图像相同.由于压缩因素,它应该看起来非常像素化!然而,压缩工作正常,因为当我将JPEG保存到磁盘时,它真的很小.
JPG:= TJPEGImage.Create;
TRY
JPG.CompressionQuality:= trkQuality.Position;
JPG.Assign(imgQInput.Picture.Graphic);
CompressJpeg(JPG);
imgQOutput.Picture.Assign(JPG); <--------- something wrong here. the shown image is not the compressed image but the original one
FINALLY
FreeAndNil(JPG);
END;
function CompressJpeg(OutJPG: TJPEGImage): Integer;
VAR tmpQStream: TMemoryStream;
begin
tmpQStream:= TMemoryStream.Create;
TRY
OutJPG.Compress;
OutJPG.SaveToStream(tmpQStream);
OutJPG.SaveToFile('c:\CompTest.jpg'); <--------------- this works
Result:= tmpQStream.Size;
FINALLY
FreeAndNil(tmpQStream);
END;
end;
Run Code Online (Sandbox Code Playgroud) 当我将控件放在窗体上时,出现此错误。错误出现在这里:
TAssociateFileExt = class(TGroupBox)
private
protected
public
btnAssociate : TButton;
constructor Create(aOwner: TComponent); override;
end;
constructor TAssociateFileExt.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
Caption:= ''; <-------- error here
ClientHeight:= 125; <-------- and here
ClientWidth := 170;
DoubleBuffered:= TRUE;
btnAssociate:= TButton.Create(Self);
btnAssociate.Parent:= Self;
btnAssociate.Visible:= TRUE;
btnAssociate.Left:= 17;
btnAssociate.Top:= 26;
btnAssociate.Width:= 142;
btnAssociate.Height:= 25;
btnAssociate.Hint:= 'Associate this application with its files. When you double click a file this program will automatically start and load that file.';
btnAssociate.Caption:= 'Associate';
btnAssociate.DoubleBuffered:= TRUE;
btnAssociate.ParentDoubleBuffered:= FALSE;
btnAssociate.TabOrder:= 0; …Run Code Online (Sandbox Code Playgroud) 我有一个项目 (C:\Test\Test.dpr) 使用属于库 (MyLib.DPK) 的文件 (External.pas)。库中的所有文件都可以通过“搜索”路径访问,但我也直接在我的 DPR 文件中包含了 External.pas:
program Test;
uses
External in '..\Packages\MyLib\External.pas', <------ the 'external' file
FormMain in 'FormMain.pas' {frmMain};
Run Code Online (Sandbox Code Playgroud)
对于这个项目,我将“输出目录”和“输出 DCU 目录”设置为“.\$(Platform)_$(Config)”。
当我编译时,这个项目的所有DCU的exe文件都写在正确的输出文件夹中:c:\Test\Win64_Debug\
但是,External.dcu 生成在 ..\Packages\MyLib\External.dcu
而不是 c:\Test\Win64_Debug\
这是为什么?
让我换个方式问这个问题:如果我将一个位于不同文件夹中的 PAS 文件附加到 DPR 项目中,那么所有 DCU 文件(包括外部文件)不应该与 EXE 文件在同一文件夹中生成吗?