C malloc "can' t allocate region”错误,但无法用 GDB 重现?

标签 c multithreading

如何调试一个 C 应用程序,它在附加 gdb 并在 gdb 内运行 run 时不会崩溃?

它在独立运行时始终崩溃 - 即使是相同的调试版本!


我们中的一些人在使用为 BSD/Linux 编写的 C 程序时遇到此错误,而我们正在使用 OpenSSL 在 macOS 上进行编译。

app(37457,0x7000017c7000) malloc: *** mach_vm_map(size=13835058055282167808) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
ERROR: malloc(buf->length + 1) failed!

我知道,没用。

使用 -g -rdynamic 重新编译应用程序会出现相同的错误。好的,现在我们知道这不是因为发布构建,因为它继续失败。

虽然它在 gdb 调试 session 中运行时有效!!

$ sudo gdb app
(gdb) b malloc_error_break
Function "malloc_error_break" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (malloc_error_break) pending.
(gdb) run -threads 8
Starting program: ~/code/app/app -threads 8
[New Thread 0x1903 of process 45436]
warning: unhandled dyld version (15)

它会运行数小时。 CTRL-C,然后运行 ​​./app -threads 8,它会在一两秒(数百万次迭代)后崩溃。

显然其中一个线程中存在问题。但是线程的那些工作人员非常大(几百行代码)。没有什么突出的。

请注意,线程以每秒约 2000 万次的循环迭代。

  • macOS 10.12.3
  • 带有 GNU gcc 和 openssl 的自制软件(链接到加密)

Ps,不太熟悉C - 尤其是任何类型的调试。回答时要友善和富有表现力/冗长。 :)

最佳答案

一种有时被忽视的调试技术是在代码中包含调试打印,当然它有缺点,但也有优点。尽管面对异常终止,您必须牢记的一件事是确保打印输出确实被打印出来。通常打印到 stderr 就足够了(但如果这不能解决问题,可能需要显式 fflush 流)。

另一个技巧是在错误发生之前停止程序。这就要求你知道程序什么时候即将崩溃,最好是越接近越好。你可以通过使用 raise 来做到这一点:

raise(SIGSTOP);

这不会终止程序,它只是暂停执行。现在您可以附加 gdb使用命令 gdb <program-name> <pid> (使用 ps 查找进程的 pid)。现在在 gdb你必须告诉它忽略 SIGSTOP :

> handle SIGSTOP ignore

然后你可以设置断点。你也可以走出raise使用 finish 的函数命令(可能需要多次发出才能返回您的代码)。

此技术使程序在您决定停止之前具有正常行为,希望是在 gdb 下运行时的最后一部分。不会足够地改变行为。

第三种选择是使用 valgrind .通常,当您看到这些类型的错误时,其中涉及的错误 valgrind会捡起来。这些是超出范围的访问和未初始化的变量。

关于C malloc "can' t allocate region”错误,但无法用 GDB 重现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43224229/

相关文章:

c - 递归期间两个连续函数如何插入堆栈

multithreading - 如何在 python 中处理大文件?

c - 来自数组的简单 Printf 循环

c - 如何打印编号给定整数可以用不同数字的总和来表示的方式?

c - 大型 C 代码无法使用 MATLAB 的 mex 进行编译

Java 在同一个 JFrame 中绘制多个正方形

python - 如何在 websockets 中使用多线程?

java - 服务器多线程一次仅应答一个客户端

ruby - `loop{}` 与 `loop{sleep 1}`

仅在 Windows 中的 C 程序编译器警告 (MinGW-w64)