我正在尝试修复一个非常大的项目中的内存泄漏。基准确认内存泄漏是一个重大问题,我正在努力寻找它们的来源。
在一个非常简单的案例中运行项目,我报告了大约850个潜在的内存泄漏。除了大约5个外,其他所有类似:
==83597== 768 bytes in 3 blocks are possibly lost in loss record 743 of 864
==83597== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==83597== by 0x548EF93: myproject_malloc (mysourcefile.c:48)
==83597== by 0x4F13FD5: ??? (in /path/to/project/library-version.so)
==83597== by 0x1101: ???
==83597== by 0xF7: ???
==83597== by 0x64D4D87: ???
==83597== by 0xFFFFFFFFFFFFFFFD: ???
==83597== by 0x6: ???
==83597== by 0x4F03BB0: ??? (in /path/to/project/library-version.so)
==83597== by 0xFFFFFFFFFFFFFFFD: ???
==83597== by 0x64D4D87: ???
==83597== 920 bytes in 1 blocks are possibly lost in loss record 750 of 864
==83597== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==83597== by 0x548EF93: myproject_malloc (mysourcefile.c:48)
==83597== by 0x4F13FD5: ??? (in /path/to/project/library-version.so)
==83597== by 0xFFEFFFD5F: ???
==83597== by 0x38F: ???
==83597== by 0xFFEFFFE5F: ???
==83597== by 0xF: ???
==83597== by 0x54542FF: ??? (in /path/to/project/library-version.so)
==83597== by 0x4F536CA: ??? (in /path/to/project/library-version.so)
==83597== by 0x64B981F: ???
==83597== by 0xF: ???
==83597== by 0x54542FF: ??? (in /path/to/project/library-version.so)
==83597== 1,360 bytes in 1 blocks are possibly lost in loss record 789 of 864
==83597== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==83597== by 0x548EF93: myproject_malloc (mysourcefile.c:48)
==83597== by 0x4F13FD5: ??? (in /path/to/project/library-version.so)
==83597== by 0x1101: ???
==83597== by 0x547: ???
==83597== by 0x1F: ???
==83597== by 0x6584267: ???
==83597== by 0x547: ???
==83597== by 0x4F13808: ??? (in /path/to/project/library-version.so)
==83597== by 0x6584267: ???
==83597== by 0x6584527: ???
==83597== by 0x65805FF: ???
我正在努力让valgrind给出真实有用的输出而不是???,但它可能是不可能的,而且我希望能够从memcheck获得有用的输出,直到发生这种情况。
有用的报告有>从真实源文件而不是.so文件报告的1个函数调用(因为每个输出都将myproject_malloc报告为潜在的泄漏源)。我能从输出中删除所有垃圾并在emacs编译缓冲区中以纯文本形式显示的最简单方法是什么?
我知道我可以通过每次输入新的错误报告并计算我看到“.c:\ d +”的次数来编写一个长达几十行的Python脚本来完成这项工作,但是我更喜欢更简单的东西。
使用命令行工具有一个很好的方法吗?或者是我不知道的valgrind选项?
答案 0 :(得分:3)
不是选项,而是配置功能:valgrind可以配置 suppress 文件,告诉它忽略某些堆栈跟踪。< / p>
有关信息,
是的!使用
--gen-suppressions=yes
功能自动为您吐出抑制。然后,您可以根据需要编辑它们,例如。使用像'*'这样的通配符组合类似的自动生成的抑制。如果您真的想手写抑制,请仔细阅读本手册。请特别注意,必须修改C ++函数名称(即,不进行解码)。
Valgrind依赖于符号。那些???
用于丢失符号(有些看起来不太可能是地址)。我记得它,valgrind在检查符号后提供那些,所以(即使有一个合适的通配符可以解决?
作为元字符),你也无法明确地压制它们。
您的堆栈跟踪缺少项目库的行号。如果使用调试(-g
)进行编译并设计合适的帧级抑制,那似乎是一种改进。
答案 1 :(得分:0)
正如我在评论中所说的那样,由于我正在使用的库的奇怪属性,基于原点的压缩不是一种合适的技术(几乎每个堆栈跟踪都通过“坏”库library-version.so
并使用-g
进行编译并不能解决问题。我最后只是写了一个python脚本,我将在这里发布给未来的用户:
#!/usr/bin/python
import fileinput
import re
START = re.compile("in loss record")
STOP = re.compile("^==\d+== $")
GOOD = re.compile(r"\.c:\d+", re.M)
def main():
in_line = False
current = []
for line in fileinput.input():
if in_line:
in_line = not STOP.search(line)
else:
in_line = START.search(line)
if in_line:
current.append(line)
else:
match = GOOD.findall("".join(current))
if len(match) > 2:
print "".join(current)
current = []
if __name__ == "__main__":
main()
现在,您可以将valgrind输出保存到文件中,也可以将其直接传送到此脚本,从而减少错误。调整len(match) > FOO
行以控制您保留的结果数量。