使用CMAKE过程中碰到的栈溢出问题总结

最近在Linux开发中使用CMKE自动生成makefile,程序运行中碰到了栈溢出的问题(实际还不太确定是不是stack overflow problem导致),于是花了很多时间细细研究了内存划分及分配等相关机制,感觉了解比以前透彻了不少,在此做一下先总结一下问题及解决方法以及还存在的疑问。

碰到的问题

先说一下碰到的问题:我们在Linux下写的程序,是一个庞大的系统,一个进程下启用了超过30个线程同时运行,某个线程中一个函数体内声明了一个大概8KB大小的数组。在原先自己写的Makefile编译运行都正常,但是采用Cmake的方式自动生成makefile,编译通过,运行的时候每次都会出现segmentation fault,backtrace显示被调用函数的入参都为0,但是上一级函数传入参数的时候,所有参数都是有值的。一进入被调用函数,就出现了core dump,gdb backtrace显示程序挂在了被调用函数的第一行。

解决办法

碰到该问题,现象有些诡异,函数调用前的入参都是有值的,一进入函数,就都变成了0。经过长时间的debug,最后确定是函数内申请的8KB数组导致的segfault。因此推断是数组导致栈溢出,覆盖了入参的值(不确定是否最终原因)。但是Linux系统默认的进程栈大小为8MB,尝试用ulimit -s 调整栈大小为16MB,仍然没有解决问题,按理说,8KB的数组并不大,但是如果将8KB分配在栈上的数组改成malloc动态分配的方式,segfault就消失了。所以解决办法就是将函数中超过1KB的数组都该成从堆上分配空间。

但是改解决办法虽然解决了出现的问题,但是还是无法解释心中的疑问:

1. 为什么8KB的数组会导致segmentation fault?

2. 如果8KB的数组造成了栈溢出从而导致segmentation fault,为何调整栈大小为原来的两倍,远远超过数组大小时,仍然没解决问题?

3. 另外就是CMAKE生成的makefile,gcc参数几乎跟自己写的makefile上的参数一样,但是原来的makfile下build的程序能够正常的执行,通过CMAKE生成makefile并build的程序却通不过,CMAKE是否有默认的设置导致程序使用的栈更小?


重新分析源程序,上面的问题又更清晰一些了。

出现segmentation fault的函数是在线程中执行的,而线程拥有自己独立的栈,共享进程所拥有的资源,这里需要区分一下线程栈与进程栈两个概念,虽然线程共享进程的资源(进程虚拟地址空间等,但是线程栈跟进程栈并不是同一块区域,线程栈所占用的空间是由系统(管理线程的进程)通过malloc动态分配堆空间所获取到的内存区域。使用ulimit -s修改的是进程的栈空间大小,但是不影响线程栈大小,线程栈大小在线程创建的时候进行设置,并且不能超过一定的大小。所以这就解释了为什么ulimit -s调整stack size为原来两倍仍然没有解决stack overflow的问题。因为pthread stack大小并没有变化。

至于使用CMAKE与不使用CMAKE自动生成makefile所build 的程序运行结果为什么不同,只能猜测也许有个别参数的差异导致两者分别build出的程序线程栈大小有差异吧,希望有CMAKE专家指点迷津。



你可能感兴趣的:(C/C++,Linux)