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,运行结果是
引用
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。杯具阿
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个字符来说非常浪费。
不知这样实现是否还有问题,欢迎看官拍板
分享到:
相关推荐
在Windows操作系统上,生成Coredump文件对于调试和分析C++程序崩溃原因至关重要。Coredump文件包含了程序崩溃时内存中的关键信息,如进程的内存映射、全局变量、堆栈信息等,使得开发者能够定位到问题的具体位置,...
在 C/C++ 程序中,数组越界或是访问空指针都会产生 SIGSEGV 信号,导致进程 crash,并产生 Core Dump 文件。为了调试 Core Dump 文件,可以使用 GDB 调试工具。GDB 是一个功能强大的调试工具,可以对 Core Dump 文件...
在线调试是在程序运行的过程中进行调试,而Coredump分析是在程序异常退出后,通过分析Coredump文件了解程序崩溃时的状态,以确定崩溃的原因。 在线调试是开发者在程序运行时进行调试的过程,可以实时查看程序的运行...
造成程序coredump的原因多种多样,常见的有以下几点: 1. 内存访问越界,比如数组越界访问、字符串未以结束符终止、使用不当的字符串处理函数等。 2. 多线程程序中使用了线程不安全的函数,包括但不限于未保护共享...
在Linux系统中,调试是解决程序异常和错误的关键步骤,特别是在遇到程序崩溃并产生coredump时。coredump是操作系统在程序异常终止时保存的内存映像,包含了程序运行时的状态,如内存布局、堆栈信息、全局变量和...
在Windows操作系统中,当应用程序崩溃或遇到不可恢复的错误时,通常会产生一个称为核心转储(core dump)的文件。核心转储文件包含了程序运行时的内存状态,这对于调试和诊断问题至关重要。"MiniDumper"是Windows...
接下来,我们引入第三方库UDumper,这是一个用于Qt项目的开源库,它简化了在Qt应用程序中生成dump文件的过程。UDumper库提供了一套API,使得在程序崩溃时能够自动生成dump文件。首先,从GitHub或其他开源平台下载...
- C++异常(C++ Exception):C++程序中引发的异常没有被正确捕获和处理。 - 局部缓冲区溢出(Local Buffer Overflow):在函数内部缓冲区被输入数据溢出,可能导致任意代码执行。 这些错误模式的分析是Linux核心...
在Windows操作系统中,当应用程序发生异常崩溃时,为了找出导致崩溃的原因,我们通常会借助于dump文件进行调试。Dump文件是系统在程序崩溃时记录的内存快照,它包含了程序运行时的关键信息,如进程内存、线程状态、...
在Windows操作系统中,当应用程序发生异常导致崩溃时,通常会丢失很多关键的调试信息。而通过生成dump文件,我们可以捕获程序崩溃时的状态,包括内存布局、线程信息、堆栈回溯等,这对于后期分析和解决问题至关重要...
标题提到的是"C++(Qt)软件调试-gdb调试入门用法(12)",这表明我们将探讨的是关于使用gdb调试C++程序,特别是与Qt相关的软件。描述中提到的是gdb调试入门用法的PDF版本,暗示我们将涵盖gdb的基础操作。标签包括"qt...
`gdb <binary> <coredump_file>`即可开始调试。 以上内容仅是Linux下C++调试技巧的一部分,实际操作中可能需要结合使用多种工具和方法,不断实践才能提升调试效率。同时,推荐阅读书籍来深入学习,以增强调试能力。
GDB(GNU Debugger)是Linux环境下用于调试C/C++程序的强大工具,尤其在处理核心转储(core dump)文件时非常有用。以下是GDB的一些关键命令及其用途的详细解释: 1. **启动GDB** - `gdb`:不带参数启动GDB,此时...
对于.NET Core项目,也可以使用Visual Studio Code搭配OmniSharp进行调试。 5. **npp_7.4.2_Installer.exe**:这个文件名可能指的是Notepad++的安装程序,这是一个流行的免费文本编辑器,尤其适用于编程。它支持...
本文将深入探讨如何使用WinDbg进行程序崩溃的调试,并提供针对C++和.NET平台的调试策略。 一、WinDbg基础 WinDbg提供了命令行和图形界面两种模式,以适应不同用户的需求。它的主要功能包括: 1. **断点设置**:...
在软件开发过程中,崩溃调试是必不可少的一个环节,尤其在C++与Qt这样的系统级编程中。传统的调试方法,如DbgHelp和qBreakpad,虽然能生成Dump文件,但它们的使用过程较为复杂,需要配置环境并调用特定库。而在Linux...
- **Windbg**:微软提供的调试工具,可用于分析DUMP文件,找出导致程序崩溃的原因。 #### 二、准备工作 在开始编写代码之前,请确保已经安装了以下组件: - Visual Studio 2010 - Microsoft Windows SDK for ...
- **定义**: GDB(GNU Debugger)是一款由GNU项目开发的开源调试工具,主要用于调试C、C++等语言编写的程序。 - **特点**: - 命令行界面:用户通过命令行交互的方式来控制调试过程。 - 强大的命令支持:提供了丰富...
6. **Core_Dump详解.doc**:讲解了C++程序崩溃时生成的芯仮转储(core dump)文件,如何分析它以找出程序崩溃的原因,使用gdb等工具进行调试的方法。 7. **C++异常规格与程序core.doc**:异常处理是C++中处理运行时...