首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程循环系统()和cout破坏堆栈

线程循环系统()和cout破坏堆栈
EN

Stack Overflow用户
提问于 2014-05-31 04:14:14
回答 1查看 489关注 0票数 4

运行以下代码的进程因分段错误而崩溃:

代码语言:javascript
复制
#include <stdlib.h>
#include <iostream>
#include <pthread.h>

void* f( void* )
{
   while( true )
   {
      // It crashes inside this call (with cerr, too).
      std::cout << 0;
   }
   return NULL;
}

int main()
{
   pthread_t t;
   pthread_create( &t, NULL, &f, NULL );

   while( true )
   {
      // It crashes with any script/app; true is just simple.
      system( "true" );
   }
   return 0;
}

它在几秒钟内崩溃了大约每一次执行(输出有数千到数百万'0's)。它用上面的代码在cout << 0调用中崩溃了几个函数。根据调用的额外函数或放在f()堆栈上的数据,它会在不同的地方崩溃。在gdb中,有时堆栈对于函数调用的顺序没有意义。由此我推断堆栈被破坏了。

我发现有一些多线程应用程序调用fork()时出现的问题 (请参阅提到堆栈损坏的两个注释)。如果文件描述符未设置为FD_CLOEXEC,则对进程进行分叉/克隆。但是,没有显式创建的文件描述符。(我尝试将FD_CLOEXEC设置在fileno( stdout )fileno( stderr )上,没有任何积极的变化。)

即使没有显式的文件描述符,我也不能混合线程和fork()吗?我是否只需要用等效的功能替换system()调用?或者,内核中是否存在导致此崩溃并在2.6.30之后修复的bug?

其他细节

我在用Linux2.6.30编译的ARM AT91处理器(armv5tejl)上运行它(带有特定外围设备的一些覆盖和补丁),用GCC 4.3.2编译。

代码语言:javascript
复制
Linux 2.6.30 #1 Thu May 29 15:43:04 CDT 2014 armv5tejl GNU/Linux

我一直在交叉编译它与-g-O0,但是没有这些,它仍然崩溃:

代码语言:javascript
复制
arm-atmel-linux-gnueabi-g++ -o system_thread system_thread.cpp -lpthread

我也尝试过-fstack-protector-all标志:有时它会在__stack_chk_fail()中崩溃,但有时其他函数指针或数据会损坏,并且会在更早的时候崩溃。

它加载的库(从strace):

代码语言:javascript
复制
libpthread.so.0
libstdc++.so.6
libm.so.6
libgcc_s.so.1
libc.so.6

注意:由于它有时不会崩溃,并且对^C没有真正的响应,所以我通常在后台运行它:

代码语言:javascript
复制
$ killall -9 system_thread; rm -f log; system_thread >log &

我已经为几个不同的架构和Linux内核版本编译了这个程序,但我没有看到它在其他地方崩溃:

代码语言:javascript
复制
Linux 3.10.29 #1 Wed Feb 12 17:12:39 CST 2014 armv5tejl GNU/Linux
Linux 3.6.0-dirty #3 Wed May 28 13:53:56 CDT 2014 microblaze GNU/Linux
Linux 3.13.0-27-generic #50-Ubuntu SMP Thu May 15 18:06:16 UTC 2014 x86_64 x86_64 GNU/Linux
Linux 3.8.0-35-generic #50~precise1-Ubuntu SMP Wed Dec 4 17:25:51 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

编辑:注意,在相同的体系结构(armv5tejl)上,它不会与Linux3.10.29崩溃。而且,在我的“设备”(旧的服务器和客户端应用程序)的早期版本上运行时,它不会崩溃,它具有相同版本的Linux2.6.30。因此,操作系统的环境有一定的影响。

BusyBox v1.20.1提供了system()调用的sh

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-05 21:39:45

这在使用您提到的2.6.30内核的ARM处理器上是可重复的,但在主处理器中则不然。我们可以使用git bisect找到这个bug的修复位置(大约需要16次迭代)。注意,由于git bisect的目的是查找回归,但在本例中,主版是“好的”,而过去的版本是“坏的”,所以我们需要颠倒“好”和“坏”的意思

二分法发现的罪魁祸首是此承诺,它修复了包含fork()的“用户空间数据损坏的实例”。此症状与您描述的症状非常相似,还可能破坏堆栈外的内存。在将此提交和所需父级移植到2.6.30内核后,您发布的代码不再崩溃。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23966310

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档