小编WeG*_*ars的帖子

FastMM4说"块头已被破坏"

我有这个令人讨厌的虫子在过去消失了,但现在经过一段时间它又回来了.

我有两个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,你能告诉我们吗?" …

delphi delphi-7 fastmm memory-corruption

5
推荐指数
1
解决办法
2740
查看次数

我可以创建与自身类型相同的对象吗?

我有一个类,我们称之为TMyObject,它应该返回一个稍微修改过的自身副本.因此,它的一个函数应该返回一个与它自身相同类型的对象:

function TMyObject.TrimEnds: TMyObject;
begin
  Result:= TMyObject.Create;
  Result.DoStuff;
edn;
Run Code Online (Sandbox Code Playgroud)

我能这样做吗?这是合法的我在做什么?

我的意思是,我已经尝试过了,编译器允许我这样做,但我想知道是否会有很长时间/隐藏的负面影响.

任何想法将不胜感激.谢谢.


编辑:新略微修改的副本将保存到磁盘.这是某种"拯救......".工作原理:原始对象创建自身的副本,指示此副本进行一些更改并保存到磁盘.然后原来释放副本.这样我保持原始对象在内存中不变,但我有一个修改版本的磁盘.

您可能认为我的对象有图片.我需要的是一个函数,它返回一个稍微修改过的图片副本.

delphi

5
推荐指数
1
解决办法
544
查看次数

如何找到TScrollBox的实际大小("逻辑区域")

我需要找到TScrollBox的整个大小(也称为"逻辑区域") - 与通过Width和Height属性(或ClientWidth ClientHeight)获得的可见区域相反.

我想在TScrollBox中创建一些控件.其中一个(称为TViewer)需要与TScrollBox本身一样高.问题是在创建过程中,TScrollBox向下滚动以显示上次创建的控件.因此,使用Top = 1将不起作用,因为我的控件将具有top = 1,这不是逻辑区域的顶部.


德尔福7

delphi

5
推荐指数
1
解决办法
6240
查看次数

如何说服内存管理器释放未使用的内存

在最近的帖子中(我的程序永远不会释放内存.为什么?)我表明在使用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刷回系统吗?当用户打开我的程序的多个实例时会发生什么?他们不会争夺内存吗?

delphi fastmm

5
推荐指数
3
解决办法
3423
查看次数

奇怪的是"名为TFrm1的组件已存在"错误


我想让用户创建同一表单的多个实例(让我们称之为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;

什么可能导致上述错误?用户发送了该错误.它只发生一次,我无法重现它.


编辑:

  1. 该错误出现在"MyFrm:= TFrm1.create"行中.

  2. 有些人建议我需要以编程方式为动态创建的表单指定唯一的名称.我也想知道自己在创建表单时所采用的名称,因此我在调用MyProcedure1过程时进入了代码.
    Delphi自动提供唯一的名称,如
    MyFrm.name = MyFrm,然后是
    MyFrm.name = MyFrm_1,
    MyFrm.name = MyFrm_2,
    MyFrm.name = MyFrm_3,依此类推.

  3. LoadFromFile中未更改MyFrm.Name.我在程序MyProcedure1的末尾检查了(断点)'MyFrm.Name'的值; 在LoadFromFile之后.这个名字很独特.

  4. 正如一些人建议的那样,我重写了SetName过程并检查了TMyFrm的名称.确实,每个表格都有一个独特的名称

    procedure TMyFrm.SetName(const Value:TComponentName);
    开始
    ShowMessage(Value);
    遗传;
    结束;

  5. 我在这个应用程序中有许多表单,但只有MainForm是自动创建的.

  6. 我不使用线程.无论如何,这是不相关的,因为表单是由用户创建的(因此多线程是无关紧要的,除非用户可以同时创建2个表单).

delphi

5
推荐指数
3
解决办法
1万
查看次数

如何将动态数据(未知字段数)存储到文件中?

我需要将一些数据存储在一个文件中.每个记录(数据集)包括:

  • 一个字符串(可变长度),
  • 一个整数数组(可变长度),
  • 一个字节数组(可变长度),
  • 一些整数值.

将所有这些东西保存在二进制文件中并不困难.但是,我确信(不幸的是)我的数据格式会随时间发生变化,我希望有可能为每个"记录"添加更多字段.所以,显然我的文件格式无法修复.我想最好的解决方案是将数据保存在(DB)表中,但我不想搞砸大枪(SQL,ADO,BDE,Nexus ......).我需要一个可以做到这一点的基础库(如果可能的话,单个PAS文件).由于这样做的目的是存储数据而不是处理数据,是否可以在没有DB表的情况下完成?

该库的要求:

  • 它需要轻松支持超过100万行
  • 非常轻巧
  • 单个PAS文件,如果可能的话
  • 强制性:易于安装在新机器中(与其编译的项目一起)
  • 强制性的:为了使用它,我不需要重新分配任何东西
  • 强制性:为了使用它,用户不必安装/设置东西
  • 可以是免费软件/共享软件
  • 它不必支持SQL查询或类似的高级内容

我用的是D7

delphi

5
推荐指数
3
解决办法
3705
查看次数

安装Delphi XE(BPL混合路径)后Delphi 7崩溃

在安装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"?

delphi

5
推荐指数
1
解决办法
918
查看次数

无法压缩JPEG图像并在屏幕上显示

我尝试在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)

delphi

5
推荐指数
1
解决办法
2153
查看次数

“控件”没有父窗口”错误

当我将控件放在窗体上时,出现此错误。错误出现在这里:

  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)

delphi delphi-xe

5
推荐指数
1
解决办法
1万
查看次数

为什么Delphi没有在正确的文件夹中输出DCU文件?

我有一个项目 (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 文件在同一文件夹中生成吗?

delphi win64 delphi-xe7

5
推荐指数
1
解决办法
4564
查看次数