【问题标题】:Debugging a crash that does not happen inside a debugger调试在调试器中不会发生的崩溃
【发布时间】:2012-09-29 09:37:28
【问题描述】:

我将一段单片代码拆分为动态加载的库和调用它的main()。除了 stdc++,我没有使用其他库,也没有任何类,只是一个没有成员函数的模板结构。我没有明确分配任何内存,也没有删除或释放代码中的任何内容。我确实使用了来自 list<T> 的擦除对象。

切换到 library + main 后,我遇到了间歇性崩溃。

*** glibc detected *** : free(): invalid pointer:

从回溯来看,似乎涉及到一个列表迭代器,但名称混乱的符号让人难以确定。

但是它不会在 gdb 中崩溃,valgrind 也不会检测到任何内存损坏或泄漏。

我之前没有构建共享库。这就是我正在使用的

g++ -fPIC -shared library_src.cpp -o libblaH.so

g++ main.cpp -lblaH

整个库都在一个源文件中,库函数包装在extern "C" 块中,以便 c 用户可以访问它,但现在我正在使用 g++ 将 main() 编译为 c++ 代码。

现在,当我添加优化选项时,-O2(特别是)我开始遇到崩溃。

我试过electricfence它说无效指针不是由malloc分配的。

我会很感激有关如何寻找错误的建议。我的感觉是我在某处使列表迭代器失效,但我不确定。我认为它们不能失效,除了已删除的条目。

【问题讨论】:

  • 如果你把所有代码放在一个单体编译单元中,错误不会出现?
  • @Walter 是的,这是正确的。好吧,它在我运行它的 10 到 15 次中都没有。但即使是库版本也不会总是崩溃,当我在标志中有 -O2 时,每 5 次就会崩溃一次,如果没有设置优化标志,也不会崩溃。
  • 如果调试器不起作用,您可以使用printf 来跟踪错误,而无需附加调试器,这样您就可以看到哪个对象在使用free 函数。
  • 尝试c++filt 对堆栈跟踪中的名称进行分解,也许对您有帮助。
  • 我知道这种类型的错误(我自己也遇到过很多次),只记得错误信息真的不是很有帮助。但是你很可能已经写入了你不应该写入的内存。我通常使用打印输出方法而不是调试(因为调试器中的事情并不总是一样的,正如您所注意到的,但打印输出语句也可能会更改代码——编译器可以重新排序并突然所有作品)

标签: c++ debugging stl crash


【解决方案1】:

出于某种原因,这对我来说是未初始化的变量。许多年前,当我像这样按小时向公司收费以帮助调试崩溃时,有一半的时候,问题是未初始化的变量。

我会使用的方法是:

  1. 系统地初始化所有变量,并在声明时将它们全部初始化。绝对没有例外。
  2. 查找无效的迭代器。即指向已擦除对象的迭代器已失效,不应使用。
  3. 寻找变量劫持。即具有相同名称的变量在同一个翻译单元中工作正常,但在单独的翻译单元中不起作用。
  4. 查找不安全的函数调用,例如 sprintf,其中格式字符串与参数不匹配。
  5. 使用#pragma 选择性地禁用部分代码的优化以缩小问题范围。有点像二分查找;禁用 1st half,仍然崩溃,2nd half 出现问题,禁用 1st half 和 1/2 of 2nd half...

我假设不涉及多个线程。当涉及线程时,可能会出现更多问题。当我在客户现场被聘用时,我总是让他们先初始化所有变量,然后再启动任何调试器。 50% 的时间我可以在第 1 步之后回家。

【讨论】:

    猜你喜欢
    • 2016-04-25
    • 1970-01-01
    • 2021-09-27
    • 2022-07-14
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多