各种奇特的事情:内存错误,无常的段错误,堆栈消失

转载于:http://blog.csdn.net/win_lin/article/details/7822762

1. 在修改较多文件,make和执行,发现总是提示SegmentFault,调试也找不到原因(gdb调试时,往往进入某个普通的函数就SegmentFault)

解决方法:全部重新编译可能会解决问题,原因不明。make clean; make。

环境:g++/gcc (GCC) 4.4.4 20100726 (Red Hat 4.4.4-13) centos6


2. 程序突然就退出了,调试时却不退出。

解决方法:可能是SIGPIPE信号导致的,Linux下默认该信号是终止程序,而在gdb下,这个信号被忽略。


3. 调用堆栈突然就消失了:

解决方法:大多是内存越界操作,而且是临时变量(栈变量),譬如声明char [256],操作时写入超过256字符,就可能改写函数的调用堆栈。


4. Centos4编译时的问题:

4.1 Centos4的gcc(3.4.6)不支持-std=C++0x参数

4.2 Centos4的多线程编程mutext的初始化,只能使用“pthread_mutex_init(&mutex, NULL);”,宏定义“PTHREAD_MUTEX_INITIALIZER;”不能使用。


5. new时段错误:

这个是最难解决的问题,因为是其他地方越界导致内存错误,在这个地方new导致问题。

Program received signal SIGSEGV, Segmentation fault.
0x00000037234787ee in _int_malloc () from /lib64/libc.so.6
(gdb) bt
#0  0x00000037234787ee in _int_malloc () from /lib64/libc.so.6
#1  0x0000003723479aed in malloc () from /lib64/libc.so.6
#2  0x00000037300bd0ed in operator new(unsigned long) () from /usr/lib64/libstdc++.so.6
#3  0x000000000040db32 in ConnectionFarm::AddClient (this=0xae34e0, client_fd=6) at connection.cpp:312

在connection.cpp:312是一个new操作:
Connection* client = new Connection(this);

碰到这个问题,就比较恐怖了。有可能是memcpy,memset,strcpy,strcat等等越界。

有个游戏界大牛(游晶 )说tcmalloc能解决这个问题,当memcpy越界时会报错。
游晶  12:47:11
http://www.google.com/#hl=zh-CN&q=tcmalloc+TCMALLOC_PAGE_FENCE&oq=tcmalloc+TCMALLOC_PAGE_FENCE&gs_l=serp.3...139786.139786.4.140233.1.1.0.0.0.0.134.134.0j1.1.0...0.0...1c.9XWRVXVVt3c&bav=on.2,or.r_gc.r_pw.&fp=3b4abcf478f33cbd&biw=1440&bih=763
http://www.cppblog.com/feixuwu/archive/2011/05/14/146395.html
不是阻止,而是在有内存访问越界的时候捕获到,例如使用guard

试了一下果然在越界的地方停下来了:

下载地址:
http://code.google.com/p/gperftools/downloads/detail?name=gperftools-2.0.tar.gz

http://download.csdn.net/download/winlinvip/4475430

[python]  view plain  copy
  1. wget http://gperftools.googlecode.com/files/gperftools-2.0.tar.gz  
  2.   
  3. #!/bin/bash  
  4.   
  5. test -z "gperftools-2.0" || tar xf gperftools-2.0.tar.gz  
  6.   
  7. echo "please modify the src/debugallocation.cc"  
  8. echo "   DEFINE_bool(malloc_page_fence,"  
  9. echo "            EnvToBool(\"TCMALLOC_PAGE_FENCE\", false),"  
  10. echo "            \"Enables putting of memory allocations at page boundaries \""  
  11. echo "            \"with a guard page following the allocation (to catch buffer \""  
  12. echo "            \"overruns right when they happen).\");"  
  13. echo "to EnvToBool(\"TCMALLOC_PAGE_FENCE\", true) and link with -ltcmalloc_debug"  
  14.   
  15. echo ""  
  16. echo "build and install:"  
  17. echo "cd  gperftools-2.0"  
  18. echo "./configure --enable-frame-pointers"  
  19. echo "make"  
  20. echo "sudo make install"  


静态库链接:
sudo ln -sf /usr/local/lib/libtcmalloc_debug.so.4 /lib64/libtcmalloc_debug.so.4

编译选项加上:

-fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free

链接选项加上:

-ltcmalloc_debug 

使用gdb调试,在越界的地方就会停下来。

举一个真实项目的例子(原型):

[cpp]  view plain  copy
  1. /** 
  2. # to build: 
  3. g++ -g -O0 -c memcorrupt.cpp -o memcorrupt.o -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free; g++ memcorrupt.o -o memcorrupt -ltcmalloc_debug ; ./memcorrupt 
  4. */  
  5. #include <stdio.h>  
  6.   
  7. class Connection;  
  8. class State  
  9. {  
  10. private:  
  11.     Connection* conn;  
  12. public:  
  13.     State(Connection* c) : conn(c){  
  14.     }  
  15.     virtual ~State(){  
  16.     }  
  17.     void action();  
  18. };  
  19.   
  20. class Manager;  
  21. class Connection  
  22. {  
  23. private:  
  24.     State* state;  
  25.     Manager* manager;  
  26. public:  
  27.     Connection(){  
  28.         state = NULL;  
  29.     }  
  30.     virtual ~Connection(){  
  31.         if(state != NULL){  
  32.             delete state;  
  33.             state = NULL;  
  34.         }  
  35.     }  
  36. public:  
  37.     void SetManager(Manager* m){  
  38.         manager = m;  
  39.     }  
  40.     Manager* GetManager(){  
  41.         return manager;  
  42.     }  
  43.     void SetState(State* s){  
  44.         state = s;  
  45.     }  
  46. };  
  47.   
  48. class Manager  
  49. {  
  50. private:  
  51.     Connection* conn;  
  52. public:  
  53.     Manager(){  
  54.         conn = NULL;  
  55.     }  
  56.     virtual ~Manager(){  
  57.     }  
  58. public:  
  59.     void Destroy(){  
  60.         if(conn != NULL){  
  61.             delete conn;  
  62.             conn = NULL;  
  63.         }  
  64.     }  
  65.     Connection* GetConnection(){  
  66.         return conn;  
  67.     }  
  68.     void SetConnection(Connection* c){  
  69.         conn = c;  
  70.         conn->SetManager(this);  
  71.     }  
  72. };  
  73.   
  74. void State::action(){  
  75.     if(conn == NULL){  
  76.         return;  
  77.     }  
  78.       
  79.     conn->GetManager()->Destroy();  
  80.     this->conn = NULL;  
  81. }  
  82.   
  83. int main(int /*argc*/char** /*argv*/){  
  84.     Manager manager;  
  85.     Connection* connection = new Connection();  
  86.     State* state = new State(connection);  
  87.       
  88.     connection->SetState(state);  
  89.     manager.SetConnection(connection);  
  90.       
  91.     state->action();  
  92.       
  93.     return 0;  
  94. }  

这段代码怎么看都没有问题,State为终止状态,将调用Manager销毁Connection对象。

有一个地方越界了:Manager.Destroy()将销毁Connection,而Connection将销毁State,在Destroy之后State的this已经不可用了,再调用this->conn=NULL就会越界。这个越界有时会有问题,有时候没有,所以很危险。

使用tcmalloc,用gdb调试时会停在越界的地方:

[python]  view plain  copy
  1. 0x000000000040079a in State::action (this=0x2aaaaaab0ff0) at memcorrupt.cpp:80  
  2. 80          this->conn = NULL;  
  3. (gdb) bt  
  4. #0  0x000000000040079a in State::action (this=0x2aaaaaab0ff0) at memcorrupt.cpp:80  
  5. #1  0x0000000000400816 in main () at memcorrupt.cpp:91  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值