我可以更改 pthread_create 以映射不在堆栈中的新线程吗?

can I change pthread_create to map new threads not in the stack?

我在 glibc-2.27 中使用 pthread.h 库,当我的进程调用 pthread_create() 十八次或更多次(它应该是一个繁重的多线程应用程序)时,进程中止并显示错误消息:

*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)

我做了一些 strace 作为调试程序的一部分,我找到了原因。显然,作为 pthread_create() 的一部分,所有对 mmap() 的隐式调用看起来像这样:

mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f6de43fa000

可以注意到 MAP_STACK 标志,它表示:

Allocate the mapping at an address suitable for a process or thread stack. This flag is currently a no-op, but is used in the glibc threading implementation so that if some architectures require special treatment for stack allocations, support can later be transparently implemented for glibc.

man mmap 在我的系统上 - Ubuntu 18.04 LTS)

可以配置 pthread_create 调用不这样做吗?或者可以使用 brk 或其他方式自动增加数据段?

感谢您的帮助!

您的问题极不可能与此 MAP_STACK 标志有关。

您的应用程序中的其他地方存在导致堆栈损坏的错误。在 valgrind 下尝试 运行 您的应用程序,或使用 -fsanitize=address 构建。两种方法都可以精确定位错误的确切位置,您应该能够据此找出问题所在。

It is possible to configure the pthread_create call not to do this?

pthread_create() 需要为线程的堆栈分配 space,否则线程不能 运行 —— 即使是空线程函数也不行。这就是您看到的 mmap 的用途。离不开。

or maybe use brk or something else to increase the data segment automatically?

如果您有时间和技能编写自己的线程库,那就试试吧,让我们知道会发生什么。否则,不,在我知道的任何实现中都无法配置 pthread_create() 如何为新线程的堆栈保留 space 的细节。

无论如何这都没有关系,因为 mmap() 调用不是问题所在。如果系统调用发生不可恢复的故障,那么就是内核故障,您会遇到内核恐慌,而不是应用程序崩溃。 GNU C 的堆栈粉碎检测发生在用户 space 中。因此,它所应用的函数不会出现在您的 strace 输出中,它仅跟踪 系统调用.

它可能对您更好地了解堆栈粉碎和 GNU 的防御措施很有用。 Dr. Dobb 运行 a nice article on just that 几年前写的,现在仍然值得一读。不过,归根结底,当函数实现通过覆盖其堆栈帧中包含其 return 地址的部分而行为不当时,就会发生堆栈粉碎。除非您正在进行一些内联​​汇编,否则几乎肯定是您自己的函数之一超过了 运行 其局部变量之一的范围。当该函数尝试 return 时,通过在用于该目的的函数尾声中使用工具来检测。