学习CoreDump

 

什么是Core Dump?
Core的意思是内存, Dump的意思是扔出来, 堆出来.
开发和使用Unix程序时, 有时程序莫名其妙的down了, 却没有任何的提示(有时候会提示core dumped). 这时候可以查看一下有没有形如core.进程号的文件生成, 这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考.
core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump.

如何使用core文件?
gdb -c core文件路径 [应用程序的路径]
进去后输入where回车, 就可以显示程序在哪一行当掉的, 在哪个函数中.

为什么没有core文件生成呢?
有时候程序down了, 但是core文件却没有生成. core文件的生成跟你当前系统的环境设置有关系, 可以用下面的语句设置一下, 然后再运行程序便成生成core文件.
ulimit -c unlimited
core文件生成的位置一般于运行程序的路径相同, 文件名一般为core.进程号

4. 用gdb查看core文件:
下面我们可以在发生运行时信号引起的错误时发生core dump了.
发生core dump之后, 用gdb进行查看core文件的内容, 以定位文件中引发core dump的行.
gdb [exec file] [core file]
如:
gdb ./test test.core
在进入gdb后, 用bt命令查看backtrace以检查发生程序运行到哪里, 来定位core dump的文件->行.
文章出处:飞诺网(www.diybl.com):http://www.diybl.com/course/3_program/c++/cppjs/20090307/158855.html

 

 

C++代码 复制代码  收藏代码
  1. class TSimpleString   
  2. {   
  3. public:   
  4.     typedef char charT;   
  5.     TSimpleString() : m_pStorage(NULL) {}   
  6.     ~TSimpleString() { clear(); }   
  7.     TSimpleString(const TSimpleString& p) { reset(p.m_pStorage); }   
  8.     TSimpleString(const charT * pStorage) { reset(pStorage); }   
  9.     TSimpleString & operator = (const TSimpleString& p) { reset(p.m_pStorage); return *this; }   
  10.     TSimpleString & operator = (const charT * pStorage) { reset(pStorage); return *this; }   
  11.   
  12.     bool            empty(voidconst   { return (m_pStorage == NULL); }   
  13.     void            clear(void);   
  14.     void            reset(const charT * pSrc);   
  15.     const charT *   get(voidconst;        //如果m_pStorage==NULL, return TStringHelper::g_strEmptyString   
  16.   
  17. private:   
  18.     charT *             m_pStorage;   
  19. };   
  20.   
  21. void TSimpleString::clear()   
  22. {   
  23.     if( m_pStorage != NULL )   
  24.     {   
  25.         delete []m_pStorage;   
  26.         m_pStorage = NULL;   
  27.     }   
  28. }   
  29.   
  30. void TSimpleString::reset(const TSimpleString::charT * pSrc)   
  31. {   
  32.     if( m_pStorage == pSrc )   
  33.         return;   
  34.   
  35.     clear();   
  36.     size_t nLen = (pSrc == NULL) ? 0 : TStringHelper::length(pSrc);   
  37.     if( nLen > 0 )   
  38.     {   
  39.         m_pStorage = new charT [nLen + 1];   
  40.         TStringHelper::strCpyByCount(m_pStorage, pSrc, nLen);   
  41.     }   
  42. }   
  43.   
  44. const TSimpleString::charT * TSimpleString::get(voidconst  
  45. {   
  46.     if( m_pStorage == NULL )   
  47.         return TStringHelper::g_strEmptyString.c_str();   
  48.     return m_pStorage;   
  49. }   
  50.   
  51. void onTestSimpleString()   
  52. {   
  53.     TSimpleString str1;   
  54.     std::cout << "str1:" << str1.get() << std::endl;   
  55.     TSimpleString str2("str2");   
  56.     std::cout << "str2:" << str2.get() << std::endl;   
  57.     TSimpleString str3(str2);   
  58.     std::cout << "str3:" << str3.get() << std::endl;   
  59.     str3 = "str3";   
  60.     std::cout << "str3:" << str3.get() << std::endl;   
  61.     TSimpleString str4 = str3;   
  62.     std::cout << "str4:" << str4.get() << std::endl;   
  63. }  



上面这段代码,运行onTestSimpleString()会coredump,运行结果是

引用

str1:
*** glibc detected *** free(): invalid pointer: 0x00cacff4 ***
Abort



刚开始还看不出哪里的问题,于是想到先让程序coredump,有了core调试就容易很多。
1,切换到root用户,再用ulimit -c 1234567设置生成core
2,执行程序,输出的结果看到已经生成core文件了

引用

str1:
*** glibc detected *** free(): invalid pointer: 0x00cacff4 ***
已放弃 (core dumped)


3,分析core

引用

(gdb) bt
#0  0x00b687a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0x00bad7a5 in raise () from /lib/tls/libc.so.6
#2  0x00baf209 in abort () from /lib/tls/libc.so.6
#3  0x00be171a in __libc_message () from /lib/tls/libc.so.6
#4  0x00be7fbf in _int_free () from /lib/tls/libc.so.6
#5  0x00be833a in free () from /lib/tls/libc.so.6
#6  0x001dbfd1 in operator delete () from /usr/lib/libstdc++.so.6
#7  0x001dc01d in operator delete[] () from /usr/lib/libstdc++.so.6
#8  0x08052375 in cmx::TSimpleString::clear (this=0xbff2b880) at ../util/testsimplestring.cpp:25
#9  0x080523a2 in cmx::TSimpleString::reset (this=0xbff2b880, pSrc=0x842e4d8 "str2") at ../util/testsimplestring.cpp:35
#10 0x08062aaa in TSimpleString (this=0xbff2b880, pStorage=0x842e4d8 "str2") at ../util/testsimplestring.cpp:8
#11 0x0805249b in cmx::onTestSimpleString () at ../util/testsimplestring.cpp:68


分析core以为是TSimpleString::reset不应该判断if( m_pStorage == pSrc ),但是去掉这个判断再运行还是出错。分析core搞不定,只好用上valgrind,用valgrind一运行,错误的地方就全部出来了。
4,运行valgrind

引用

==30827== Conditional jump or move depends on uninitialised value(s)
==30827==    at 0x8052393: TSimpleString::reset(char const*) (testsimplestring.cpp:32)
==30827==    by 0x8062AA9: TSimpleString::TSimpleString(char const*) (testsimplestring.cpp:8)
==30827==    by 0x805249A: onTestSimpleString() (testsimplestring.cpp:68)


可看出在第8行根据const charT * pStorage构造TSimpleString时调用了TSimpleString::reset,而在TSimpleString::reset的32行使用了未初始化的m_pStorage。这时再看回TSimpleString(const charT * pStorage) { reset(pStorage); }就知道,确实是还没初始化m_pStorage。杯具阿

C++代码 复制代码  收藏代码
  1. TSimpleString(const TSimpleString& p) { reset(p.m_pStorage); }   
  2. TSimpleString(const charT * pStorage) { reset(pStorage); }  


这两行代码都没有初始化就使用了m_pStorage,应该改成

C++代码 复制代码  收藏代码
  1. TSimpleString(const TSimpleString& p) : m_pStorage(NULL) { reset(p.m_pStorage); }   
  2. TSimpleString(const charT * pStorage) : m_pStorage(NULL) { reset(pStorage); }  



再说下写这个类的目的:
因为要存储很多长度很短(只有10来个字符)的字符串对象,这些对象一旦保存后就不再修改,并且很多时候这些字符串是空的,所以不想用std::string来保存。因为std::string不管有没有存储内容都要用3个指针,这对于只存储10个字符来说非常浪费。

不知这样实现是否还有问题,欢迎看官拍板

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值