C++程序coredump及调试过程


class TSimpleString
{
public:
typedef char charT;
TSimpleString() : m_pStorage(NULL) {}
~TSimpleString() { clear(); }
TSimpleString(const TSimpleString& p) { reset(p.m_pStorage); }
TSimpleString(const charT * pStorage) { reset(pStorage); }
TSimpleString & operator = (const TSimpleString& p) { reset(p.m_pStorage); return *this; }
TSimpleString & operator = (const charT * pStorage) { reset(pStorage); return *this; }

bool empty(void) const { return (m_pStorage == NULL); }
void clear(void);
void reset(const charT * pSrc);
const charT * get(void) const; //如果m_pStorage==NULL, return TStringHelper::g_strEmptyString

private:
charT * m_pStorage;
};

void TSimpleString::clear()
{
if( m_pStorage != NULL )
{
delete []m_pStorage;
m_pStorage = NULL;
}
}

void TSimpleString::reset(const TSimpleString::charT * pSrc)
{
if( m_pStorage == pSrc )
return;

clear();
size_t nLen = (pSrc == NULL) ? 0 : TStringHelper::length(pSrc);
if( nLen > 0 )
{
m_pStorage = new charT [nLen + 1];
TStringHelper::strCpyByCount(m_pStorage, pSrc, nLen);
}
}

const TSimpleString::charT * TSimpleString::get(void) const
{
if( m_pStorage == NULL )
return TStringHelper::g_strEmptyString.c_str();
return m_pStorage;
}

void onTestSimpleString()
{
TSimpleString str1;
std::cout << "str1:" << str1.get() << std::endl;
TSimpleString str2("str2");
std::cout << "str2:" << str2.get() << std::endl;
TSimpleString str3(str2);
std::cout << "str3:" << str3.get() << std::endl;
str3 = "str3";
std::cout << "str3:" << str3.get() << std::endl;
TSimpleString str4 = str3;
std::cout << "str4:" << str4.get() << std::endl;
}


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

[quote]
str1:
*** glibc detected *** free(): invalid pointer: 0x00cacff4 ***
Abort
[/quote]

刚开始还看不出哪里的问题,于是想到先让程序coredump,有了core调试就容易很多。
1,切换到root用户,再用ulimit -c 1234567设置生成core
2,执行程序,输出的结果看到已经生成core文件了
[quote]
str1:
*** glibc detected *** free(): invalid pointer: 0x00cacff4 ***
已放弃 (core dumped)
[/quote]
3,分析core
[quote]
(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
[/quote]
分析core以为是TSimpleString::reset不应该判断if( m_pStorage == pSrc ),但是去掉这个判断再运行还是出错。分析core搞不定,只好用上valgrind,用valgrind一运行,错误的地方就全部出来了。
4,运行valgrind
[quote]
==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)
[/quote]
可看出在第8行根据const charT * pStorage构造TSimpleString时调用了TSimpleString::reset,而在TSimpleString::reset的32行使用了未初始化的m_pStorage。这时再看回TSimpleString(const charT * pStorage) { reset(pStorage); }就知道,确实是还没初始化m_pStorage。杯具阿

TSimpleString(const TSimpleString& p) { reset(p.m_pStorage); }
TSimpleString(const charT * pStorage) { reset(pStorage); }

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

TSimpleString(const TSimpleString& p) : m_pStorage(NULL) { reset(p.m_pStorage); }
TSimpleString(const charT * pStorage) : m_pStorage(NULL) { reset(pStorage); }


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

不知这样实现是否还有问题,欢迎看官拍板
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值