I have been running FastMM4 on my code to see if I have any memory leaks...
This has reported a load of class UniCodeString leaks when I close the program. Are these real and how do I interpret the Event Log: This is a typical block report:
--------------------------------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 . . . . .
Run Code Online (Sandbox Code Playgroud)
Most of the leaks are small, less than 200 bytes but should I be worrying about them?
Rem*_*eau 15
这些是真的吗
非常可能。特别是你展示的那个,是的。
我如何解释事件日志
您显示的泄漏报告表明 aUnicodeString已泄漏。 UnicodeString是托管类型。我见过UnicodeString泄露的唯一时间是:
它是classor的成员record,并且该类型的动态分配的实例本身已泄漏。泄漏报告应显示此实例也被泄漏。
UnicodeString由于意外覆盖,指向已分配的指针已损坏,通常是由代码中某处的逻辑错误造成的。
它被声明为 athreadvar并且在线程退出之前不会被手动清除。这是记录在案的行为:
通常由编译器管理的动态变量(长字符串、宽字符串、动态数组、变体和接口)可以用 声明
threadvar,但编译器不会自动释放每个执行线程创建的堆分配内存。如果您在线程变量中使用这些数据类型,则您有责任在线程终止之前从线程内部处理它们的内存。
让我们更仔细地查看您显示的报告。
内存块已泄漏。尺码为:120
不言自明。分配大小为 120 字节的内存块被泄露。
该块由线程 0x5648 分配,当时的堆栈跟踪(返回地址)为:
430547 [FastMM4.pas][FastMM4][_ZN7Fastmm411DebugGetMemEx][8737]
409534 [System.pas][系统][_ZN6System7_GetMemEx][4803]
412F8C [System.pas][System][_ZN6System17_NewUnicodeStringEi][25403]
414C3C [System.pas][System][_ZN6System16InternalUSrCatNERNS_13UnicodeStringEiPS0_][29902]
4156CB [System.pas][系统][_ZN6System9_USrCatNERNS_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][_ZN6Ideini15TIDEIniSettings4SaveEiiiiiibjPN6System7Classes8TStringsENS1_13UnicodeStringE][1078]
14DE604 [IDEMain.pas][IDEMain][_ZN7Idemain10TfmIDEMain9FormCloseEPN6System7TObjectERNS1_7Utypepes12TCloseActionE][573]
泄漏的内存由 ID 为0x5648运行时的线程分配。堆栈跟踪显示了导致泄漏内存块分配的函数调用链。在这种情况下,堆栈跟踪从您的TForm.OnClose事件处理程序开始,因此该线程显然是主 UI 线程。实际的函数调用链是:
IDEMain.TfmIDEMain.FormClose()in IDEMain.pas,其中调用:IDEIni.TIDEIniSettings.Save()in IDEIni.pas,其中调用:IDEIni.TIDEIniSettings.UpdateSection(Integer)in IDEIni.pas,其中调用:IDEIni.TIDEIniSettings.UpdateSection(UnicodeString)in IDEIni.pas,其中调用:System.IniFiles.TMemIniFile.WriteString()in System.IniFiles.pas,其中调用:System.IniFiles.TMemIniFile.TSection.SetValues()in System.IniFiles.pas,其中调用:System._UStrCatN()in System.pas,其中调用:System.InternalUStrCatN()in System.pas,其中调用:System._NewUnicodeString()in System.pas,其中调用:System._GetMem()in System.pas,其中调用:FastMM4.DebugGetMem()in FastMM4.pas,它分配了泄漏的内存因此,您的OnClose处理程序正在将一个字符串值保存到一个.INI文件中,并且在内部该 write 在 内部执行了一个字符串连接TSection.SetValues(),其结果被泄露。我猜是因为连接的字符串保存在一个TSection本身泄漏的对象中。
该块当前用于类的对象:UnicodeString
不言自明。
分配号为:675683
FastMM 会跟踪它在程序生命周期内执行了多少内存分配。
从指针地址 7FF4FBF7E170 开始的 256 字节的当前内存转储:
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
$Ù我。°。. . . . . . )。. . 。一种 。吨。H 。= . C 。:。\ .
。r 。哦。G 。r 。一种 。米。. F 。一世 。升。电子。。. ( 。 X 。
8 . 6 . )。\ . 。r 。哦。吨。哦。名词。一世 。D. 乙。\ . 。D.
。. . Ê š õ ¯ Õò ÿ € € € € € € € € € € € € € € € € €
. . . . . . . . ã÷ûô。. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . 7 小时。. G 。C 。. . . . ¶ C 。. . . .
• @。. . . . . TA。. . . . . UA 。. . . . . 维。. . . .
C 。F 。. . . . 一种 。F 。. . . . ' > H 。. . . . ¥ . 一种 。. . . .
这是泄漏的内存块中原始数据的转储。该块位于内存地址$7FF4FBF7E170。前半部分是原始字节的十六进制格式表示,后半部分是这些字节的人类可读的 ASCII 解释。
由于我们知道该块属于 a UnicodeString,我们可以进一步挖掘数据。
AUnicodeString以StrRec标题开头:
A memory block has been leaked. The size is: 120
日志中使用的名称 mangling 的格式告诉我您使用的是基于 Clang 的编译器之一,因此如果我们假设是 64 位编译器,那么StrRec大小将是 16 个字节,如果我们分解前 16 个字节在转储中,我们得到以下值:
24 D9 69 01 _Padding,忽略 B0 04 代码页 = 1200,UTF-16 02 00 elemSize = 2, sizeof(WideChar) 01 00 00 00 refCnt = 1 29 00 00 00 长度 = 41 WideChar 元素
这与有效的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 转储:
。一种 。吨。H 。= . C 。:。\ . 。r 。哦。G 。r 。一种 。米。. F 。一世 。升。电子。。. ( 。 X 。 8 . 6 . )。\ . 。r 。哦。吨。 哦。名词。一世 。D. 乙。\ . 。D. 。. .
其中,考虑到 UTF-16,形成了 Unicode 字符串值:
'Path=C:\Program Files (x86)\ProtonIDE\PDS'
那是泄漏的实际字符串。在结合动作TSection.SetValues()很可能加入子'Path','='和'C:\Program Files (x86)\ProtonIDE\PDS'一起,假设TMemIniFile.WriteString()有被称为是这样的:
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]
剩下的转储数据只是碰巧在同一个内存块中的随机垃圾,因为 FastMM 在固定大小的块中分配内存。在这种情况下,泄漏的数据UnicodeString被分配在一个使用 120 字节块的桶中。
如果我不得不猜测,要么你泄露了TMemIniFile对象(它应该出现在泄漏报告的其他地方),或者TMemIniFile你的 Delphi 版本有一个逻辑错误,泄漏了一个TSection对象(它应该出现在泄漏报告的其他地方)。您现在可以在此处开始调试代码以跟踪泄漏的根本原因。
| 归档时间: |
|
| 查看次数: |
227 次 |
| 最近记录: |