这些内存泄漏是真的吗
Are these Memory Leaks Real
我已经运行在我的代码上使用 FastMM4 来查看我是否有任何内存泄漏...
当我关闭程序时,这报告了 class UniCodeString 负载泄漏。这些是真实的吗?我如何解释事件日志:这是典型的块报告:
--------------------------------2020/10/21 17:32:01--------------------------------
A memory block has been leaked. The size is: 120
This block was allocated by thread 0x5648, and the stack trace (return addresses) at the time was:
430547 [FastMM4.pas][FastMM4][_ZN7Fastmm411DebugGetMemEx][8737]
409534 [System.pas][System][_ZN6System7_GetMemEx][4803]
412F8C [System.pas][System][_ZN6System17_NewUnicodeStringEi][25403]
414C3C [System.pas][System][_ZN6System16InternalUStrCatNERNS_13UnicodeStringEiPS0_][29902]
4156CB [System.pas][System][_ZN6System9_UStrCatNERNS_13UnicodeStringEi][30998]
5DD71A [System.IniFiles.pas][System.IniFiles][_ZN6System8Inifiles11TMemIniFile8TSection9SetValuesEiNS_13UnicodeStringE][852]
5DEFA6 [System.IniFiles.pas][System.IniFiles][_ZN6System8Inifiles11TMemIniFile11WriteStringENS_13UnicodeStringES2_S2_][1212]
14F335F [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings13UpdateSectionEN6System13UnicodeStringE][1153]
14F26E7 [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings13UpdateSectionEi][1087]
14F24FD [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings4SaveEiiiiibjPN6System7Classes8TStringsENS1_13UnicodeStringE][1078]
14DE604 [IDEMain.pas][IDEMain][_ZN7Idemain10TfmIDEMain9FormCloseEPN6System7TObjectERNS1_7Uitypes12TCloseActionE][573]
The block is currently used for an object of class: UnicodeString
The allocation number is: 675683
Current memory dump of 256 bytes starting at pointer address 7FF4FBF7E170:
24 D9 69 01 B0 04 02 00 01 00 00 00 29 00 00 00 50 00 61 00 74 00 68 00 3D 00 43 00 3A 00 5C 00
50 00 72 00 6F 00 67 00 72 00 61 00 6D 00 20 00 46 00 69 00 6C 00 65 00 73 00 20 00 28 00 78 00
38 00 36 00 29 00 5C 00 50 00 72 00 6F 00 74 00 6F 00 6E 00 49 00 44 00 45 00 5C 00 50 00 44 00
53 00 00 00 CA 9A 8A F5 AF D5 F2 FF 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
00 00 00 00 00 00 00 00 81 E3 F7 FB F4 7F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 37 48 0A 00 47 05 43 00 00 00 00 00 B6 08 43 00 00 00 00 00
9D 95 40 00 00 00 00 00 1C 54 41 00 00 00 00 00 11 55 41 00 00 00 00 00 01 56 45 01 00 00 00 00
63 02 46 01 00 00 00 00 E2 1E 46 01 00 00 00 00 92 9B 68 00 00 00 00 00 A5 04 41 00 00 00 00 00
$ Ù i . ° . . . . . . . ) . . . P . a . t . h . = . C . : . \ .
P . r . o . g . r . a . m . . F . i . l . e . s . . ( . x .
8 . 6 . ) . \ . P . r . o . t . o . n . I . D . E . \ . P . D .
S . . . Ê š Š õ ¯ Õ ò ÿ € € € € € € € € € € € € € € € € € € € €
. . . . . . . . ã ÷ û ô . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . 7 H . . G . C . . . . . ¶ . C . . . . .
• @ . . . . . . T A . . . . . . U A . . . . . . V E . . . . .
c . F . . . . . â . F . . . . . ’ › h . . . . . ¥ . A . . . . .
大多数泄漏都很小,不到 200 字节,但我应该担心它们吗?
Are these real
很有可能。尤其是你展示的那个,不错。
how do I interpret the Event Log
您显示的泄漏报告表明 UnicodeString
已泄漏。 UnicodeString
是托管类型。我唯一一次看到 UnicodeString
被泄露的时间是:
它是 class
或 record
的成员,并且该类型的动态分配实例本身已泄漏。泄漏报告应该会显示此实例也已泄漏。
指向分配的 UnicodeString
的指针由于意外覆盖而损坏,通常是代码中某处的逻辑错误。
它被声明为一个threadvar
并且在线程退出之前不会被手动清除。这是 documented behavior:
Dynamic variables that are ordinarily managed by the compiler (long strings, wide strings, dynamic arrays, variants, and interfaces) can be declared with threadvar
, but the compiler does not automatically free the heap-allocated memory created by each thread of execution. If you use these data types in thread variables, it is your responsibility to dispose of their memory from within the thread, before the thread terminates.
让我们更仔细地看看您显示的报告。
A memory block has been leaked. The size is: 120
Self-explanatory。分配的大小为 120 字节的内存块已泄漏。
This block was allocated by thread 0x5648, and the stack trace (return addresses) at the time was:
430547 [FastMM4.pas][FastMM4][_ZN7Fastmm411DebugGetMemEx][8737]
409534 [System.pas][System][_ZN6System7_GetMemEx][4803]
412F8C [System.pas][System][_ZN6System17_NewUnicodeStringEi][25403]
414C3C [System.pas][System][_ZN6System16InternalUStrCatNERNS_13UnicodeStringEiPS0_][29902]
4156CB [System.pas][System][_ZN6System9_UStrCatNERNS_13UnicodeStringEi][30998]
5DD71A [System.IniFiles.pas][System.IniFiles][_ZN6System8Inifiles11TMemIniFile8TSection9SetValuesEiNS_13UnicodeStringE][852]
5DEFA6 [System.IniFiles.pas][System.IniFiles][_ZN6System8Inifiles11TMemIniFile11WriteStringENS_13UnicodeStringES2_S2_][1212]
14F335F [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings13UpdateSectionEN6System13UnicodeStringE][1153]
14F26E7 [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings13UpdateSectionEi][1087]
14F24FD [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings4SaveEiiiiibjPN6System7Classes8TStringsENS1_13UnicodeStringE][1078]
14DE604 [IDEMain.pas][IDEMain][_ZN7Idemain10TfmIDEMain9FormCloseEPN6System7TObjectERNS1_7Uitypes12TCloseActionE][573]
泄漏的内存是由 ID 为 0x5648
的线程在运行时分配的。堆栈跟踪显示导致分配泄漏的内存块的函数调用链。在这种情况下,堆栈跟踪从您的 TForm.OnClose
事件处理程序开始,因此该线程显然是主 UI 线程。实际的函数调用链是:
IDEMain.TfmIDEMain.FormClose()
在 IDEMain.pas
中调用了:
IDEIni.TIDEIniSettings.Save()
在 IDEIni.pas
中调用了:
IDEIni.TIDEIniSettings.UpdateSection(Integer)
在 IDEIni.pas
中调用了:
IDEIni.TIDEIniSettings.UpdateSection(UnicodeString)
在 IDEIni.pas
中调用了:
System.IniFiles.TMemIniFile.WriteString()
在 System.IniFiles.pas
中调用了:
System.IniFiles.TMemIniFile.TSection.SetValues()
在 System.IniFiles.pas
中调用了:
System._UStrCatN()
在 System.pas
中调用了:
System.InternalUStrCatN()
在 System.pas
中调用了:
System._NewUnicodeString()
在 System.pas
中调用了:
System._GetMem()
在 System.pas
中调用了:
FastMM4.DebugGetMem()
in FastMM4.pas
,它分配了泄漏的内存
因此,您的 OnClose
处理程序将字符串值保存到 .INI
文件,并且在内部写入在 TSection.SetValues()
中执行了字符串连接,其结果被泄露.我猜是因为连接的字符串保存在 TSection
object 中,它本身就被泄露了。
The block is currently used for an object of class: UnicodeString
Self-explanatory.
The allocation number is: 675683
FastMM 跟踪它在程序的生命周期内执行了多少内存分配。
Current memory dump of 256 bytes starting at pointer address 7FF4FBF7E170:
24 D9 69 01 B0 04 02 00 01 00 00 00 29 00 00 00 50 00 61 00 74 00 68 00 3D 00 43 00 3A 00 5C 00
50 00 72 00 6F 00 67 00 72 00 61 00 6D 00 20 00 46 00 69 00 6C 00 65 00 73 00 20 00 28 00 78 00
38 00 36 00 29 00 5C 00 50 00 72 00 6F 00 74 00 6F 00 6E 00 49 00 44 00 45 00 5C 00 50 00 44 00
53 00 00 00 CA 9A 8A F5 AF D5 F2 FF 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
00 00 00 00 00 00 00 00 81 E3 F7 FB F4 7F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 37 48 0A 00 47 05 43 00 00 00 00 00 B6 08 43 00 00 00 00 00
9D 95 40 00 00 00 00 00 1C 54 41 00 00 00 00 00 11 55 41 00 00 00 00 00 01 56 45 01 00 00 00 00
63 02 46 01 00 00 00 00 E2 1E 46 01 00 00 00 00 92 9B 68 00 00 00 00 00 A5 04 41 00 00 00 00 00
$ Ù i . ° . . . . . . . ) . . . P . a . t . h . = . C . : . \ .
P . r . o . g . r . a . m . . F . i . l . e . s . . ( . x .
8 . 6 . ) . \ . P . r . o . t . o . n . I . D . E . \ . P . D .
S . . . Ê š Š õ ¯ Õ ò ÿ € € € € € € € € € € € € € € € € € € € €
. . . . . . . . ã ÷ û ô . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . 7 H . . G . C . . . . . ¶ . C . . . . .
• @ . . . . . . T A . . . . . . U A . . . . . . V E . . . . .
c . F . . . . . â . F . . . . . ’ › h . . . . . ¥ . A . . . . .
这是泄漏的内存块中原始数据的转储。该块位于内存地址 FF4FBF7E170
。前半部分是原始字节的 hex-formatted 表示,后半部分是这些字节的 human-readable ASCII 解释。
因为我们知道该块属于 UnicodeString
,我们可以进一步挖掘数据。
A UnicodeString
以 StrRec
header:
开头
StrRec = packed record
{$IF defined(CPUX64)}
_Padding: LongInt; // Make 16 byte align for payload..
{$ENDIF}
codePage: Word;
elemSize: Word;
refCnt: Longint;
length: Longint;
end;
日志中使用的名称修改格式告诉我您正在使用 Clang-based 编译器之一,因此如果我们假设一个 64 位编译器,那会使 StrRec
为 16 字节在大小上,如果我们分解转储的前 16 个字节,我们将得到以下值:
24 D9 69 01 _Padding, ignored
B0 04 codePage = 1200, UTF-16
02 00 elemSize = 2, sizeof(WideChar)
01 00 00 00 refCnt = 1
29 00 00 00 length = 41 WideChar elements
符合有效UnicodeString
。因此,如果我们再查看转储中接下来的 ((41+1)*2)=84
个字节,我们会看到以下内容:
50 00 61 00 74 00 68 00 3D 00 43 00 3A 00 5C 00
50 00 72 00 6F 00 67 00 72 00 61 00 6D 00 20 00
46 00 69 00 6C 00 65 00 73 00 20 00 28 00 78 00
38 00 36 00 29 00 5C 00 50 00 72 00 6F 00 74 00
6F 00 6E 00 49 00 44 00 45 00 5C 00 50 00 44 00
53 00 00 00
并且来自相应的 ASCII 转储:
P . a . t . h . = . C . : . \ .
P . r . o . g . r . a . m . .
F . i . l . e . s . . ( . x .
8 . 6 . ) . \ . P . r . o . t .
o . n . I . D . E . \ . P . D .
S . . .
考虑到 UTF-16,形成 Unicode 字符串值:
'Path=C:\Program Files (x86)\ProtonIDE\PDS'
这就是泄露的实际字符串。 TSection.SetValues()
中的串联操作很可能将子字符串 'Path'
、'='
和 'C:\Program Files (x86)\ProtonIDE\PDS'
连接在一起,假设 TMemIniFile.WriteString()
是这样调用的:
var Ini: TMemIniFile;
...
Ini.WriteString('Path', 'C:\Program Files (x86)\ProtonIDE\PDS');
剩下的转储数据只是碰巧在同一个内存块中的随机垃圾,因为 FastMM 在 fixed-sized 块的桶中分配内存。在这种情况下,泄漏的 UnicodeString
被分配到一个使用 120 字节块的桶中。
如果我不得不猜测,要么是你泄露了 TMemIniFile
object(应该出现在泄露报告的其他地方),要么是你的 [=160= 版本中的 TMemIniFile
] 有一个逻辑错误,会泄漏 TSection
object(应该出现在泄漏报告的其他地方)。您现在可以从这里开始调试代码以追踪泄漏的根本原因。
我已经运行在我的代码上使用 FastMM4 来查看我是否有任何内存泄漏...
当我关闭程序时,这报告了 class UniCodeString 负载泄漏。这些是真实的吗?我如何解释事件日志:这是典型的块报告:
--------------------------------2020/10/21 17:32:01--------------------------------
A memory block has been leaked. The size is: 120
This block was allocated by thread 0x5648, and the stack trace (return addresses) at the time was:
430547 [FastMM4.pas][FastMM4][_ZN7Fastmm411DebugGetMemEx][8737]
409534 [System.pas][System][_ZN6System7_GetMemEx][4803]
412F8C [System.pas][System][_ZN6System17_NewUnicodeStringEi][25403]
414C3C [System.pas][System][_ZN6System16InternalUStrCatNERNS_13UnicodeStringEiPS0_][29902]
4156CB [System.pas][System][_ZN6System9_UStrCatNERNS_13UnicodeStringEi][30998]
5DD71A [System.IniFiles.pas][System.IniFiles][_ZN6System8Inifiles11TMemIniFile8TSection9SetValuesEiNS_13UnicodeStringE][852]
5DEFA6 [System.IniFiles.pas][System.IniFiles][_ZN6System8Inifiles11TMemIniFile11WriteStringENS_13UnicodeStringES2_S2_][1212]
14F335F [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings13UpdateSectionEN6System13UnicodeStringE][1153]
14F26E7 [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings13UpdateSectionEi][1087]
14F24FD [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings4SaveEiiiiibjPN6System7Classes8TStringsENS1_13UnicodeStringE][1078]
14DE604 [IDEMain.pas][IDEMain][_ZN7Idemain10TfmIDEMain9FormCloseEPN6System7TObjectERNS1_7Uitypes12TCloseActionE][573]
The block is currently used for an object of class: UnicodeString
The allocation number is: 675683
Current memory dump of 256 bytes starting at pointer address 7FF4FBF7E170:
24 D9 69 01 B0 04 02 00 01 00 00 00 29 00 00 00 50 00 61 00 74 00 68 00 3D 00 43 00 3A 00 5C 00
50 00 72 00 6F 00 67 00 72 00 61 00 6D 00 20 00 46 00 69 00 6C 00 65 00 73 00 20 00 28 00 78 00
38 00 36 00 29 00 5C 00 50 00 72 00 6F 00 74 00 6F 00 6E 00 49 00 44 00 45 00 5C 00 50 00 44 00
53 00 00 00 CA 9A 8A F5 AF D5 F2 FF 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
00 00 00 00 00 00 00 00 81 E3 F7 FB F4 7F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 37 48 0A 00 47 05 43 00 00 00 00 00 B6 08 43 00 00 00 00 00
9D 95 40 00 00 00 00 00 1C 54 41 00 00 00 00 00 11 55 41 00 00 00 00 00 01 56 45 01 00 00 00 00
63 02 46 01 00 00 00 00 E2 1E 46 01 00 00 00 00 92 9B 68 00 00 00 00 00 A5 04 41 00 00 00 00 00
$ Ù i . ° . . . . . . . ) . . . P . a . t . h . = . C . : . \ .
P . r . o . g . r . a . m . . F . i . l . e . s . . ( . x .
8 . 6 . ) . \ . P . r . o . t . o . n . I . D . E . \ . P . D .
S . . . Ê š Š õ ¯ Õ ò ÿ € € € € € € € € € € € € € € € € € € € €
. . . . . . . . ã ÷ û ô . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . 7 H . . G . C . . . . . ¶ . C . . . . .
• @ . . . . . . T A . . . . . . U A . . . . . . V E . . . . .
c . F . . . . . â . F . . . . . ’ › h . . . . . ¥ . A . . . . .
大多数泄漏都很小,不到 200 字节,但我应该担心它们吗?
Are these real
很有可能。尤其是你展示的那个,不错。
how do I interpret the Event Log
您显示的泄漏报告表明 UnicodeString
已泄漏。 UnicodeString
是托管类型。我唯一一次看到 UnicodeString
被泄露的时间是:
它是
class
或record
的成员,并且该类型的动态分配实例本身已泄漏。泄漏报告应该会显示此实例也已泄漏。指向分配的
UnicodeString
的指针由于意外覆盖而损坏,通常是代码中某处的逻辑错误。它被声明为一个
threadvar
并且在线程退出之前不会被手动清除。这是 documented behavior:Dynamic variables that are ordinarily managed by the compiler (long strings, wide strings, dynamic arrays, variants, and interfaces) can be declared with
threadvar
, but the compiler does not automatically free the heap-allocated memory created by each thread of execution. If you use these data types in thread variables, it is your responsibility to dispose of their memory from within the thread, before the thread terminates.
让我们更仔细地看看您显示的报告。
A memory block has been leaked. The size is: 120
Self-explanatory。分配的大小为 120 字节的内存块已泄漏。
This block was allocated by thread 0x5648, and the stack trace (return addresses) at the time was: 430547 [FastMM4.pas][FastMM4][_ZN7Fastmm411DebugGetMemEx][8737] 409534 [System.pas][System][_ZN6System7_GetMemEx][4803] 412F8C [System.pas][System][_ZN6System17_NewUnicodeStringEi][25403] 414C3C [System.pas][System][_ZN6System16InternalUStrCatNERNS_13UnicodeStringEiPS0_][29902] 4156CB [System.pas][System][_ZN6System9_UStrCatNERNS_13UnicodeStringEi][30998] 5DD71A [System.IniFiles.pas][System.IniFiles][_ZN6System8Inifiles11TMemIniFile8TSection9SetValuesEiNS_13UnicodeStringE][852] 5DEFA6 [System.IniFiles.pas][System.IniFiles][_ZN6System8Inifiles11TMemIniFile11WriteStringENS_13UnicodeStringES2_S2_][1212] 14F335F [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings13UpdateSectionEN6System13UnicodeStringE][1153] 14F26E7 [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings13UpdateSectionEi][1087] 14F24FD [IDEIni.pas][IDEIni][_ZN6Ideini15TIDEIniSettings4SaveEiiiiibjPN6System7Classes8TStringsENS1_13UnicodeStringE][1078] 14DE604 [IDEMain.pas][IDEMain][_ZN7Idemain10TfmIDEMain9FormCloseEPN6System7TObjectERNS1_7Uitypes12TCloseActionE][573]
泄漏的内存是由 ID 为 0x5648
的线程在运行时分配的。堆栈跟踪显示导致分配泄漏的内存块的函数调用链。在这种情况下,堆栈跟踪从您的 TForm.OnClose
事件处理程序开始,因此该线程显然是主 UI 线程。实际的函数调用链是:
IDEMain.TfmIDEMain.FormClose()
在IDEMain.pas
中调用了:IDEIni.TIDEIniSettings.Save()
在IDEIni.pas
中调用了:IDEIni.TIDEIniSettings.UpdateSection(Integer)
在IDEIni.pas
中调用了:IDEIni.TIDEIniSettings.UpdateSection(UnicodeString)
在IDEIni.pas
中调用了:System.IniFiles.TMemIniFile.WriteString()
在System.IniFiles.pas
中调用了:System.IniFiles.TMemIniFile.TSection.SetValues()
在System.IniFiles.pas
中调用了:System._UStrCatN()
在System.pas
中调用了:System.InternalUStrCatN()
在System.pas
中调用了:System._NewUnicodeString()
在System.pas
中调用了:System._GetMem()
在System.pas
中调用了:FastMM4.DebugGetMem()
inFastMM4.pas
,它分配了泄漏的内存
因此,您的 OnClose
处理程序将字符串值保存到 .INI
文件,并且在内部写入在 TSection.SetValues()
中执行了字符串连接,其结果被泄露.我猜是因为连接的字符串保存在 TSection
object 中,它本身就被泄露了。
The block is currently used for an object of class: UnicodeString
Self-explanatory.
The allocation number is: 675683
FastMM 跟踪它在程序的生命周期内执行了多少内存分配。
Current memory dump of 256 bytes starting at pointer address 7FF4FBF7E170: 24 D9 69 01 B0 04 02 00 01 00 00 00 29 00 00 00 50 00 61 00 74 00 68 00 3D 00 43 00 3A 00 5C 00 50 00 72 00 6F 00 67 00 72 00 61 00 6D 00 20 00 46 00 69 00 6C 00 65 00 73 00 20 00 28 00 78 00 38 00 36 00 29 00 5C 00 50 00 72 00 6F 00 74 00 6F 00 6E 00 49 00 44 00 45 00 5C 00 50 00 44 00 53 00 00 00 CA 9A 8A F5 AF D5 F2 FF 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 00 00 00 00 00 00 00 00 81 E3 F7 FB F4 7F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 37 48 0A 00 47 05 43 00 00 00 00 00 B6 08 43 00 00 00 00 00 9D 95 40 00 00 00 00 00 1C 54 41 00 00 00 00 00 11 55 41 00 00 00 00 00 01 56 45 01 00 00 00 00 63 02 46 01 00 00 00 00 E2 1E 46 01 00 00 00 00 92 9B 68 00 00 00 00 00 A5 04 41 00 00 00 00 00 $ Ù i . ° . . . . . . . ) . . . P . a . t . h . = . C . : . \ . P . r . o . g . r . a . m . . F . i . l . e . s . . ( . x . 8 . 6 . ) . \ . P . r . o . t . o . n . I . D . E . \ . P . D . S . . . Ê š Š õ ¯ Õ ò ÿ € € € € € € € € € € € € € € € € € € € € . . . . . . . . ã ÷ û ô . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 H . . G . C . . . . . ¶ . C . . . . . • @ . . . . . . T A . . . . . . U A . . . . . . V E . . . . . c . F . . . . . â . F . . . . . ’ › h . . . . . ¥ . A . . . . .
这是泄漏的内存块中原始数据的转储。该块位于内存地址 FF4FBF7E170
。前半部分是原始字节的 hex-formatted 表示,后半部分是这些字节的 human-readable ASCII 解释。
因为我们知道该块属于 UnicodeString
,我们可以进一步挖掘数据。
A UnicodeString
以 StrRec
header:
StrRec = packed record
{$IF defined(CPUX64)}
_Padding: LongInt; // Make 16 byte align for payload..
{$ENDIF}
codePage: Word;
elemSize: Word;
refCnt: Longint;
length: Longint;
end;
日志中使用的名称修改格式告诉我您正在使用 Clang-based 编译器之一,因此如果我们假设一个 64 位编译器,那会使 StrRec
为 16 字节在大小上,如果我们分解转储的前 16 个字节,我们将得到以下值:
24 D9 69 01 _Padding, ignored B0 04 codePage = 1200, UTF-16 02 00 elemSize = 2, sizeof(WideChar) 01 00 00 00 refCnt = 1 29 00 00 00 length = 41 WideChar elements
符合有效UnicodeString
。因此,如果我们再查看转储中接下来的 ((41+1)*2)=84
个字节,我们会看到以下内容:
50 00 61 00 74 00 68 00 3D 00 43 00 3A 00 5C 00 50 00 72 00 6F 00 67 00 72 00 61 00 6D 00 20 00 46 00 69 00 6C 00 65 00 73 00 20 00 28 00 78 00 38 00 36 00 29 00 5C 00 50 00 72 00 6F 00 74 00 6F 00 6E 00 49 00 44 00 45 00 5C 00 50 00 44 00 53 00 00 00
并且来自相应的 ASCII 转储:
P . a . t . h . = . C . : . \ . P . r . o . g . r . a . m . . F . i . l . e . s . . ( . x . 8 . 6 . ) . \ . P . r . o . t . o . n . I . D . E . \ . P . D . S . . .
考虑到 UTF-16,形成 Unicode 字符串值:
'Path=C:\Program Files (x86)\ProtonIDE\PDS'
这就是泄露的实际字符串。 TSection.SetValues()
中的串联操作很可能将子字符串 'Path'
、'='
和 'C:\Program Files (x86)\ProtonIDE\PDS'
连接在一起,假设 TMemIniFile.WriteString()
是这样调用的:
var Ini: TMemIniFile;
...
Ini.WriteString('Path', 'C:\Program Files (x86)\ProtonIDE\PDS');
剩下的转储数据只是碰巧在同一个内存块中的随机垃圾,因为 FastMM 在 fixed-sized 块的桶中分配内存。在这种情况下,泄漏的 UnicodeString
被分配到一个使用 120 字节块的桶中。
如果我不得不猜测,要么是你泄露了 TMemIniFile
object(应该出现在泄露报告的其他地方),要么是你的 [=160= 版本中的 TMemIniFile
] 有一个逻辑错误,会泄漏 TSection
object(应该出现在泄漏报告的其他地方)。您现在可以从这里开始调试代码以追踪泄漏的根本原因。