【问题标题】:Delphi memory leak when adding language添加语言时的Delphi内存泄漏
【发布时间】:2013-07-14 16:20:57
【问题描述】:

Delphi XE,Windows 7 64 位

当您向空应用程序添加语言支持时,您将收到内存泄漏 (FastMM4)。

如何重现:

  • 创建新的 VCL 表单应用程序
  • 修改.dpr并添加ReportMemoryLeaksOnShutdown := True;
  • 构建/运行应用程序并关闭应用程序 -> 未报告任何泄漏
  • 现在添加一种语言(项目 -> 语言 -> 添加)
  • 再次构建/运行并关闭应用程序 -> 内存泄漏??

FastMM4 完整调试模式报告:

--------------------------------2013/7/16 14:54:34--------------------------------
A memory block has been leaked. The size is: 12

This block was allocated by thread 0x17EC, and the stack trace (return addresses) at the time was:
40455E 
40952D 
4094C8 
409834 
409941 
450058 
74548D76 [Unknown function at FirstHookFunc]
7778FA1A [ZwOpenKey]
75924033 [OpenRegKey]
759240AE [OpenRegKey]
777FA71A [Unknown function at RtlUlonglongByteSwap]

The block is currently used for an object of class: Unknown

The allocation number is: 6

Current memory dump of 256 bytes starting at pointer address 7EF9A610:
6E 00 6C 00 2D 00 42 00 45 00 00 00 41 58 0D 7A 00 00 00 00 C1 A6 F9 7E 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 2E 00 00 00 5E 45 40 00 DD 99 40 00 6D 71 4B 00 98 65 40 00 04 66 40 00
77 A6 40 00 98 7C 4B 00 AA 33 8D 76 F2 9E 7A 77 C5 9E 7A 77 00 00 00 00 EC 17 00 00 EC 17 00 00
1F 9A 40 00 53 7F 42 00 2C 65 40 00 EA 68 40 00 E3 7C 4B 00 AA 33 8D 76 F2 9E 7A 77 C5 9E 7A 77
00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 B6 5C 27 4D 5C 12 4C 00 80 80 80 80
49 A3 D8 B2 80 80 80 80 00 00 00 00 F9 B7 F9 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
65 00 00 00 5E 45 40 00 A7 50 40 00 22 56 40 00 DC 50 40 00 5F 72 4B 00 78 96 44 00 8E 72 4B 00
98 65 40 00 04 66 40 00 77 A6 40 00 98 7C 4B 00 EC 17 00 00 EC 17 00 00 7A 45 40 00 C5 50 40 00
n  .  l  .  -  .  B  .  E  .  .  .  A  X  .  z  .  .  .  .  Á  ¦  ù  ~  .  .  .  .  .  .  .  .
.  .  .  .  .  .  .  .  .  .  .  .  ^  E  @  .  Ý  ™  @  .  m  q  K  .  ˜  e  @  .  .  f  @  .
w  ¦  @  .  ˜  |  K  .  ª  3    v  ò  ž  z  w  Å  ž  z  w  .  .  .  .  ì  .  .  .  ì  .  .  .
.  š  @  .  S    B  .  ,  e  @  .  ê  h  @  .  ã  |  K  .  ª  3    v  ò  ž  z  w  Å  ž  z  w
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  ¶  \  '  M  \  .  L  .  €  €  €  €
I  £  Ø  ²  €  €  €  €  .  .  .  .  ù  ·  ù  ~  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
e  .  .  .  ^  E  @  .  §  P  @  .  "  V  @  .  Ü  P  @  .  _  r  K  .  x  –  D  .  Ž  r  K  .
˜  e  @  .  .  f  @  .  w  ¦  @  .  ˜  |  K  .  ì  .  .  .  ì  .  .  .  z  E  @  .  Å  P  @  .

--------------------------------2013/7/16 14:54:34--------------------------------
This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):

5 - 12 bytes: Unknown x 1

Note: Memory leak detail is logged to a text file in the same folder as this application. To disable this memory leak check, undefine "EnableMemoryLeakReporting".

现在到有趣的部分:删除语言并再次运行 -> 泄漏仍然存在!

我可以通过删除除 .dpr 和 .res 文件之外的所有项目相关文件(.dproj、.dproj2007、.dsk 等)来消除泄漏。

谁能解释一下这是怎么回事?

更新

使用详细日志中的地址,我似乎在 System.Pas 中发现了泄漏:

var
  PreferredLanguagesOverride: PChar = nil;

...    
procedure SetLocaleOverride(const NewPreferredLanguages: string);
var
  L: Integer;
begin
  if PreferredLanguagesOverride <> nil then
    FreeMem(PreferredLanguagesOverride);
  L := Length(NewPreferredLanguages);
  if L > 0 then
  begin
    Inc(L);
    GetMem(PreferredLanguagesOverride, L * SizeOf(Char));
    MoveChars(NewPreferredLanguages[1], PreferredLanguagesOverride^, L);
  end;
end;

调用SetLocaleOverride 并为PreferredLanguagesOverride PChar 保留内存。我在 System.Pas 中扫描了FreeMem(PreferredLanguagesOverride),但这是唯一一次出现!

更新2

我找到了delphi调用SetLocaleOverride例程的原因:

当您添加语言支持时,会创建一个注册表项,其名称为可执行完整路径,当前系统区域设置为值: HKEY_CURRENT_USER\Software\Embarcadero\Locales

删除此键可防止 delphi 调用 SetLocaleOverride 例程。

问题:

  • 谁能验证这个问题在以后的Delphi版本中是否存在? (否则我会做一份质量控制报告)

更新 3

已经有一个 QC report (105136) 并且已经从 XE3 修复了

问题:谁能告诉我这是如何在 XE3 中修补的?

【问题讨论】:

  • 提交 QC 报告,并致电 RegisterExpectedMemoryLeak。
  • 无法在 Delphi XE3、Windows 7 64 位中重现...
  • @Tlama:谢谢,显然它已在您的版本中修复:)

标签: delphi memory-leaks delphi-xe


【解决方案1】:

正如我在问题中已经说过的,这是从 XE3 中修复的。

对于低版本的,你可以修补System.pas。

procedure _Halt0 的行前添加SetLocaleOverride('');

FinalizeUnits;

这将消除内存泄漏。

很高兴知道:How to recompile System.pas

如果您不想重新编译 System.pas,可以在 finalization 部分中调用 SetLocaleOverride('');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多