C 难以跟踪内存损坏-使用Valgrind运行时运行正常,无错误

C 难以跟踪内存损坏-使用Valgrind运行时运行正常,无错误,c,multithreading,valgrind,memory-corruption,C,Multithreading,Valgrind,Memory Corruption,我们有一个复杂的程序,在重载输入(实际上是任何输入)上运行良好,没有实现多线程。 我们已经用线程池实现了多线程,并且给出了这些输入参数,我得到了以下结果: (注意:如果我说没有错误,这意味着我用valgrind-v进行了测试,如果我说没有内存泄漏,这意味着我用valgrind--leak check=full-v进行了测试) 小文件:使用1个以上的工作线程成功运行,没有valgrind错误,没有内存泄漏 medium\u文件:使用1个工作进程,它成功运行,没有错误/内存泄漏。超过1名员工,我得到

我们有一个复杂的程序,在重载输入(实际上是任何输入)上运行良好,没有实现多线程。
我们已经用线程池实现了多线程,并且给出了这些输入参数,我得到了以下结果:
注意:如果我说没有错误,这意味着我用
valgrind-v
进行了测试,如果我说没有内存泄漏,这意味着我用
valgrind--leak check=full-v
进行了测试)

  • 小文件:使用1个以上的工作线程成功运行,没有valgrind错误,没有内存泄漏
  • medium\u文件:使用1个工作进程,它成功运行,没有错误/内存泄漏。超过1名员工,我得到:a。通常是堆损坏错误,b。双重免费。使用
    valgrind-v
    和>1个工人运行时,程序成功完成。此外,valgrind没有打印错误,即
    错误摘要:0个上下文中的0个错误(已抑制:2个来自2)
    既然我没有从valgrind那里得到任何错误,那么我该如何在这个复杂的大型应用程序中发现内存损坏问题呢

    开发环境:

    Ubuntu,64位,gcc版本:4.7.2和4.8.1(不同的计算机,Ubuntu的更新版本)。

    请使用核心转储::[主要用于双自由,glibc检测到的类型错误]

    使用gcc-g选项编译程序以获取调试信息

    ulimit-a 它将显示核心文件的大小

    ulimit-c无限 它将设置核心文件的大小不受限制

    现在运行程序,然后在当前目录中生成一个名为“core”的文件

    然后由GDB进行如下分析

    gdb./YOU项目核心 gdb)英国电信 它会告诉你问题出在哪里

    如果你发现任何困难,请写信给我

    既然我没有从valgrind那里得到任何错误,那么我该如何在这个复杂的大型应用程序中发现内存损坏问题呢

    好吧,让我向你们描述一下我在上世纪90年代在微软的JavaScript实现中发现内存泄漏的原因

    首先,我确保在我的程序的调试版本中,尽可能多的内存分配被路由到相同的helper方法。也就是说,我重新定义了
    malloc
    new
    ,等等,这些都是我自己编写的分配器的同义词

    该分配器只是操作系统虚拟堆内存分配器的薄壳,但它有一些额外的智能。它在块的开头和结尾分配了额外的内存,并用sentinel值、到目前为止分配数量的线程安全计数以及所有分配的线程安全双链接列表填充该内存。“自由”程序将验证双方的哨兵值是否仍然完整;如果不是,那么某个地方就有内存损坏。它将从链接列表中取消块的链接并释放它

    在任何时候,我都可以要求内存管理器按照分配的顺序列出内存中所有未完成的块。卸载DLL时,列表中剩余的任何项都是内存泄漏

    这些工具使我能够很容易地实时发现内存泄漏和内存损坏

    超过1名员工,我得到:a。通常堆损坏错误,b.双自由。 当使用valgrind-v运行且工作线程数大于1时,程序将成功完成

    基于以上症状,我认为您的程序中显然存在某种同步问题。看起来您的程序在线程之间共享堆内存地址,因此每当遇到数据竞争问题时

    您还提到,当您运行valgrind-v时,您的程序将成功完成。这表明您的程序存在同步问题,这也取决于顺序/计时。这些是最难发现的bug之一。我们还应该记住,动态工具在程序运行并执行错误之前不会给出任何警告。我的意思是程序中可能有问题,但执行顺序(因为存在一些与时间相关的问题)决定了工具是否能够捕获这些故障


    话虽如此,我认为在大型程序中找不到这样的bug,但我强烈怀疑存在导致内存损坏/双重释放的数据竞赛场景。因此,您可能希望使用Helgrind检查/查找可能导致内存损坏的数据争用/线程问题

    Coredump对于发现如此严重的内存损坏以及如此庞大/复杂的程序也没有多大用处。堆损坏通常会在一段时间后影响/崩溃程序。所以从转储文件中会包含一些信息,这些信息可能是在程序中之前做了一些不好的事情之后产生的。所以这些调用堆栈不会有多大用处…非常感谢,我以前没听说过Helgrind!我已经找到了数据竞争条件,并用互斥锁保护它们。现在一切都好了!我想这正是valgrind所做的。