我可以更改 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 时,通过在用于该目的的函数尾声中使用工具来检测。
我在 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 时,通过在用于该目的的函数尾声中使用工具来检测。