调试Mac上的分段错误?

ele*_*uid 4 c debugging macos gcc segmentation-fault

我在使用Mac上运行导致分段错误的程序时出现问题.我正在为IOCCC整理一个条目,这意味着我的计划有以下几点:

  • 它是一个名为prog.c的单个文件中的一个非常小的C程序
  • 我不会在这里发布,因为它不会帮助(并且可能会使比赛条目无效)
  • 它使用"cc -o prog prog.c -Wall"在gcc下干净地编译
  • 尽管(或者,更确切地说,因为)它包含了许多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秒钟没有任何事情发生(我的程序成功运行大约需要一分钟),但它只是说"分段错误",然后结束.

以下是我尝试过的,使用从这个有用的StackOverflow线程收集的答案来追踪问题:

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

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

我没有想法.我试图让Cygwin设置(虽然花了好几个小时),看看是否有任何工具可以这样工作,但如果失败那么我就不知所措了.当然必须有一些能够跟踪Mac上分段错误原因的工具吗?

Bre*_*nks 7

你有编译-g并运行它gdb吗?一旦应用程序崩溃,您可以获得一个回溯,bt它应该显示崩溃发生的位置

  • 请注意,在较新的操作系统/Xcode 版本上,您可以使用“lldb”。不过,它的工作原理是一样的。 (3认同)
  • 完善!我以前没有使用过gdb,但是它立即解决了问题,并以XCode彻底失败的方式使问题变得很清楚。如果有人感兴趣,我的问题似乎归结为Macbook Pro处理浮点算术的方式。我的代码包含一个递归函数,当在很小的定义公差范围内找到正确的答案时,该函数将停止递归,但是在Macbook上它似乎还不够接近,因此它会永久递归并炸毁调用堆栈(呵呵,堆栈溢出)。 )。增加公差可以解决所有问题。 (2认同)
  • 在此处插入对<每位计算机科学家应该知道的有关浮点的信息>的参考。 (2认同)

Roy*_*rot 6

为了更现代的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
...
Run Code Online (Sandbox Code Playgroud)


nyb*_*bon 6

在许多情况下,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/