【问题标题】:Debugging Segmentation Faults on a Mac?在 Mac 上调试分段错误?
【发布时间】:2012-01-12 07:36:35
【问题描述】:

在 Mac 上运行时,我遇到了一些导致分段错误的程序问题。我正在为IOCCC 整理一个条目,这意味着我的程序有以下几点:

  • 这是一个非常小的 C 程序,位于一个名为 prog.c 的文件中
  • 我不会在此处发布它,因为它无济于事(并且可能会使参赛作品无效)
  • 它在 gcc 下使用“cc -o prog prog.c -Wall”干净地编译
  • 尽管(或者,更准确地说,因为)它包含一堆非常奇怪的 C 用法,但它的构造非常谨慎。我不知道它的任何部分与内存无关(这并不是说不可能有错误,只是如果有它们不太可能是明显的错误)
  • 我主要是 Windows 用户,但几年前我在几台 Windows 机器、几台 Mac 和一个 Linux 机器上成功编译并运行了它,没有任何问题。从那以后代码没有改变,但我不再可以访问这些机器。

我没有要重新测试的 Linux 机器,但作为最终测试,我尝试在 MacBook Pro - Mac OSX 10.6.7、Xcode 4.2(即 GCC 4.2.1)上编译和运行它。同样,它可以从命令行干净地编译。似乎在 Mac 上键入“prog”不会使编译后的程序运行,但“open prog”似乎可以。大约 10 秒内什么也没有发生(我的程序在成功后大约需要一分钟才能运行),然后它只是说“Segmentation fault”,然后结束。

这是我尝试使用的大部分从 this useful StackOverflow thread 收集的答案来追踪问题的方法:

  • 在 Windows 上,在代码中添加 _ASSERTE(_CrtCheckMemory()); - 代码运行缓慢,但运行成功。没有任何断言被触发(当我故意添加糟糕的代码以确保 _CrtCheckMemory 和 _ASSERTE 按预期工作时,它们会触发,但不会触发)
  • 在 Mac 上,我尝试了 Mudflap。我尝试使用“g++ -fmudflap -fstack-protector-all -lmudflap -Wall -o prog prog.c”的变体来构建代码,它只会产生错误“cc1plus: error: mf-runtime.h: No such file或目录”。谷歌搜索这件事并没有得出任何结论,但似乎确实有一种感觉,即 Mudflap 在 Mac 上不起作用。
  • 同样在 Mac 上,我尝试了 Valgrind。我安装并构建了它,并使用“cc -o prog -g -O0 prog.c”构建了我的代码。使用命令“valgrind --leak-check=yes prog”运行 Valgrind 会产生错误“valgrind: prog: command not found”。记住你让你在 Mac 上“打开”了一个可执行文件,我尝试了“valgrind --leak-check=yes open prog”,它似乎可以运行该程序,并且还运行 Valgrind,它没有发现任何问题。但是,即使我使用专门设计用于触发错误消息的程序运行 Valgrind,它也无法为我找到问题。我这在 Mac 上也坏了?
  • 我尝试在 Xcode 中运行该程序,在 Product->Edit Scheme... 菜单中勾选了所有诊断复选框,并在 malloc_error_break 中设置了符号断点。断点未命中,代码停止在一个包含一件事(“dlopen”)的调用堆栈中,输出窗口中显示的唯一注意事项如下:

警告:无法恢复之前选择的帧。 现在没有可用于编程的内存:调用 malloc 不安全

我没有想法。我正在尝试设置 Cygwin(尽管这需要几个小时)以查看是否有任何工具可以以这种方式工作,但如果失败了,那我就不知所措了。肯定有一些工具能够在 Mac 上追踪分段错误的原因吗?

【问题讨论】:

  • 与任何 UNIX 一样,除非 prog 在您的 PATH 中,否则您需要指定 prog 的路径才能运行它,例如./prog 来自它所在的目录。上面的 valgrind 调用也是如此;应该是valgrind --leak-check=yes ./prog。不要使用open 运行您的代码。
  • 至于无法访问 Linux 机器……是认真的吗?只需下载 Ubuntu 的 Live CD 映像,将其放在 CD/USB 驱动器上,然后启动到... OMG Ponies!这就像完全 Linux。 (抱歉有点刻薄,但弄清楚这个解决方案确实要求你是火箭外科医生。)

标签: c macos debugging gcc segmentation-fault


【解决方案1】:

您是否使用-g 编译并在gdb 中运行它?应用程序崩溃后,您可以使用bt 获取回溯,它应该会告诉您崩溃发生的位置

【讨论】:

  • 完美!我以前没有使用过 gdb,但它立即解决了问题,并以 XCode 完全而悲惨地未能做到的方式明确了问题。如果有人感兴趣,我的问题似乎归结为 Macbook Pro 处理浮点运算的方式。我的代码包含一个递归函数,当它在一个小的定义公差内找到正确答案时停止递归,但在 Macbook 上它似乎从来没有足够接近,所以它永远递归并炸毁了调用堆栈(呵呵,堆栈溢出 .. .)。增加容差可以解决所有问题。
  • 在此处插入对的引用。
  • 请注意,在较新的 OS/Xcode 版本上,您使用 lldb 代替。不过,它的工作原理是一样的。
  • 十年后(2021 年 9 月)成就了我的一天。谢谢。
【解决方案2】:

为了更现代的lldb 风味

$ lldb --file /path/to/program
...
(lldb) r
Process 89510 launched
...
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x726f00)
  * frame #0: 0x00007fff73856e52 libsystem_platform.dylib`_platform_strlen + 18
...

【讨论】:

  • 谢谢,这是救命稻草。
【解决方案3】:

在很多情况下,macOS 将最近的程序崩溃日志存储在 ~/Library/Logs/DiagnosticReports/ 文件夹下。

在 macOS 上进行故障排除时,我通常会尝试以下步骤:

  1. 清理~/Library/Logs/DiagnosticReports/下现有的崩溃日志
  2. 再次运行程序以重现问题
  3. 等待几秒钟,崩溃日志将出现在文件夹下。崩溃日志命名为{your_program}_{crashing_date}_{id}_{your_host}.crash
  4. 使用文本编辑器打开崩溃日志,搜索关键字Crashed 以定位导致崩溃的线程。它会在崩溃期间向您显示堆栈跟踪,并且在许多情况下,还会记录导致崩溃的确切源代码行。

一些链接:

[1]https://mac-optimization.bestreviews.net/analyze-mac-crash-reports/

【讨论】:

    猜你喜欢
    • 2021-01-04
    • 1970-01-01
    • 2021-06-04
    • 2012-05-11
    • 2015-02-18
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    相关资源
    最近更新 更多