`
wengshanjin
  • 浏览: 23588 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
社区版块
存档分类
最新评论

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,运行结果是

引用

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个字符来说非常浪费。

不知这样实现是否还有问题,欢迎看官拍板
分享到:
评论

相关推荐

    window COREdump文件生成 c++代码

    在Windows操作系统上,生成Coredump文件对于调试和分析C++程序崩溃原因至关重要。Coredump文件包含了程序崩溃时内存中的关键信息,如进程的内存映射、全局变量、堆栈信息等,使得开发者能够定位到问题的具体位置,...

    coredump文件调试

    在 C/C++ 程序中,数组越界或是访问空指针都会产生 SIGSEGV 信号,导致进程 crash,并产生 Core Dump 文件。为了调试 Core Dump 文件,可以使用 GDB 调试工具。GDB 是一个功能强大的调试工具,可以对 Core Dump 文件...

    GDB之在线调试与Coredump分析

    在线调试是在程序运行的过程中进行调试,而Coredump分析是在程序异常退出后,通过分析Coredump文件了解程序崩溃时的状态,以确定崩溃的原因。 在线调试是开发者在程序运行时进行调试的过程,可以实时查看程序的运行...

    Coredump简介及使用

    造成程序coredump的原因多种多样,常见的有以下几点: 1. 内存访问越界,比如数组越界访问、字符串未以结束符终止、使用不当的字符串处理函数等。 2. 多线程程序中使用了线程不安全的函数,包括但不限于未保护共享...

    Linux Debugging(五): coredump 分析入門1

    在Linux系统中,调试是解决程序异常和错误的关键步骤,特别是在遇到程序崩溃并产生coredump时。coredump是操作系统在程序异常终止时保存的内存映像,包含了程序运行时的状态,如内存布局、堆栈信息、全局变量和...

    MiniDumper windos下写coredump文件的类

    在Windows操作系统中,当应用程序崩溃或遇到不可恢复的错误时,通常会产生一个称为核心转储(core dump)的文件。核心转储文件包含了程序运行时的内存状态,这对于调试和诊断问题至关重要。"MiniDumper"是Windows...

    qt vs编译器下生成dump文件,方便调试。

    接下来,我们引入第三方库UDumper,这是一个用于Qt项目的开源库,它简化了在Qt应用程序中生成dump文件的过程。UDumper库提供了一套API,使得在程序崩溃时能够自动生成dump文件。首先,从GitHub或其他开源平台下载...

    Accelerated Linux Core Dump Analysis Training Course

    - C++异常(C++ Exception):C++程序中引发的异常没有被正确捕获和处理。 - 局部缓冲区溢出(Local Buffer Overflow):在函数内部缓冲区被输入数据溢出,可能导致任意代码执行。 这些错误模式的分析是Linux核心...

    Windows调试(通过dump文件定位崩溃)

    在Windows操作系统中,当应用程序发生异常崩溃时,为了找出导致崩溃的原因,我们通常会借助于dump文件进行调试。Dump文件是系统在程序崩溃时记录的内存快照,它包含了程序运行时的关键信息,如进程内存、线程状态、...

    Windows程序崩溃后通过代码产生完整dump

    在Windows操作系统中,当应用程序发生异常导致崩溃时,通常会丢失很多关键的调试信息。而通过生成dump文件,我们可以捕获程序崩溃时的状态,包括内存布局、线程信息、堆栈回溯等,这对于后期分析和解决问题至关重要...

    C++(Qt)软件调试-gdb调试入门用法(12)

    标题提到的是"C++(Qt)软件调试-gdb调试入门用法(12)",这表明我们将探讨的是关于使用gdb调试C++程序,特别是与Qt相关的软件。描述中提到的是gdb调试入门用法的PDF版本,暗示我们将涵盖gdb的基础操作。标签包括"qt...

    linux下C++调试技巧

    `gdb &lt;binary&gt; &lt;coredump_file&gt;`即可开始调试。 以上内容仅是Linux下C++调试技巧的一部分,实际操作中可能需要结合使用多种工具和方法,不断实践才能提升调试效率。同时,推荐阅读书籍来深入学习,以增强调试能力。

    GDB调试core文件最常用的

    GDB(GNU Debugger)是Linux环境下用于调试C/C++程序的强大工具,尤其在处理核心转储(core dump)文件时非常有用。以下是GDB的一些关键命令及其用途的详细解释: 1. **启动GDB** - `gdb`:不带参数启动GDB,此时...

    java c++ PHP c# 代码快速调试工具

    对于.NET Core项目,也可以使用Visual Studio Code搭配OmniSharp进行调试。 5. **npp_7.4.2_Installer.exe**:这个文件名可能指的是Notepad++的安装程序,这是一个流行的免费文本编辑器,尤其适用于编程。它支持...

    WinDbg 调试程序崩溃操作详解

    本文将深入探讨如何使用WinDbg进行程序崩溃的调试,并提供针对C++和.NET平台的调试策略。 一、WinDbg基础 WinDbg提供了命令行和图形界面两种模式,以适应不同用户的需求。它的主要功能包括: 1. **断点设置**:...

    C++(Qt)软件崩溃调试-学会使用ProcDump (5)20230402.pdf

    在软件开发过程中,崩溃调试是必不可少的一个环节,尤其在C++与Qt这样的系统级编程中。传统的调试方法,如DbgHelp和qBreakpad,虽然能生成Dump文件,但它们的使用过程较为复杂,需要配置环境并调用特定库。而在Linux...

    vs2010如何修改工程使得应用程序崩溃自动生成dump文件

    - **Windbg**:微软提供的调试工具,可用于分析DUMP文件,找出导致程序崩溃的原因。 #### 二、准备工作 在开始编写代码之前,请确保已经安装了以下组件: - Visual Studio 2010 - Microsoft Windows SDK for ...

    GDB调试程序文档

    - **定义**: GDB(GNU Debugger)是一款由GNU项目开发的开源调试工具,主要用于调试C、C++等语言编写的程序。 - **特点**: - 命令行界面:用户通过命令行交互的方式来控制调试过程。 - 强大的命令支持:提供了丰富...

    C++高级应用完整版

    6. **Core_Dump详解.doc**:讲解了C++程序崩溃时生成的芯仮转储(core dump)文件,如何分析它以找出程序崩溃的原因,使用gdb等工具进行调试的方法。 7. **C++异常规格与程序core.doc**:异常处理是C++中处理运行时...

Global site tag (gtag.js) - Google Analytics