删除对象时出现段错误 - GDB 在 free() 中说

Posted

技术标签:

【中文标题】删除对象时出现段错误 - GDB 在 free() 中说【英文标题】:Segfault when I delete an object - GDB says in free() 【发布时间】:2010-02-28 23:28:01 【问题描述】:

我正在处理一项网络任务,我们应该在 C 中创建一个网络库,然后在我们的 C++ 程序中使用它。我的 C++ 不如我的 C 强大,所以我首先开始使用它,这样我就可以解决出现的任何问题,我向您介绍我的第一个问题。 :D

我有一个基类和一个继承类(最终会有另一个继承的),它们将提供确定服务器行为的函数。

基类头和析构函数:

    // Message Forwarder Base Class 
class MessageForwarder

public:
    /* ------ Public Function Declarations ------ */
    MessageForwarder(const string serverName, const string serverAddress);
    virtual ~MessageForwarder();
    virtual void Print() const = 0; 

protected:
    /* ------ Private Variable Declarations ------ */
    string monitor; // 192.168.1.102:8000 - The address to the monitoring server
    string myName; // The name of message forwarding server
    string myAddress; // The address of the message forwarding server
;    

MessageForwarder::~MessageForwarder()

    delete &this->monitor;
    delete &this->myName;
    delete &this->myAddress;
    fprintf(stdout, "Cleaning up MessageForwarder\n");

继承的类和析构函数:

// Client Message Forwarder Derived Class
class ClientMessageForwarder : public MessageForwarder

public:
    /* ------ Public Function Declarations ------ */
    ClientMessageForwarder(const string serverName, const string serverAddress);
    ~ClientMessageForwarder();
    void Print() const; 

private:
    /* ------ Private Variable Declarations ------ */

;

ClientMessageForwarder::~ClientMessageForwarder()

    fprintf(stdout, "Cleaning up ClientMessageHandler\n");

当我尝试删除一个类对象时出现了我的问题。我的程序如下:

int main(int argc, char *argv[])

    /* ------ Variable Declarations ------ */

// Server Object
MessageForwarder *msgFrwder;

msgFrwder = new ClientMessageForwarder(serverName, serverAddress);
msgFrwder->Print();
delete msgFrwder; <------------ SEGFAULT here!

return 0;

当我继续运行我的程序时,它会在删除 msgFrwder 行上出现段错误;我继续使用带有转储核心的 GDB,并询问它发生在哪里,它给了我以下信息:

#0  0x0000000800afe409 in free () from /lib/libc.so.7
#1  0x00000008006cbd17 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string () from /usr/lib/libstdc++.so.6
#2  0x0000000000401e88 in ~MessageForwarder (this=0x800d02080) at ./classes/msgfrwd.cpp:44
#3  0x00000000004023c5 in ~ClientMessageForwarder (this=0x800d02080) at ./classes/climsgfrwd.cpp:44
#4  0x000000000040158c in main (argc=7, argv=0x7fffffffe478) at ./msgfrwdserver.cpp:97

以我有限的 C++ 知识,我觉得我正在按照正确的步骤来清理和释放我的内存。当我运行我的程序时,它实际上会输出“Cleaning up MessageForwarder”,所以我知道它执行了该行。

我一直在寻找解决方案,并为这个问题苦苦挣扎了一段时间,但找不到解决方案。任何帮助将不胜感激,或者解释实际发生的情况以及发生段错误的原因会有所帮助。

感谢您的所有帮助。其赞赏。 :D

【问题讨论】:

【参考方案1】:

字符串对象不是使用new 运算符分配的。不要删除它们,它们会被自动释放

【讨论】:

那么我只能删除我用 new 创建的对象吗?至于它们是否会在退出程序或调用类析构函数时自动释放? @Chris 基本上发生的是对象析构函数调用每个成员变量的析构函数,从而不需要显式析构(除非您使用原始指针)。一般来说是的,delete 与 new 一起使用,但在使用 new[] 的地方要小心,因为那样你就必须使用 delete[] @Chris:一般规则是——不管它是什么产生的(malloc、new、new[],隐式通过堆栈)——你必须使用相反的(free、delete、delete[] , 隐式通过堆栈)。 @Chris:这将在MessageForwarder的销毁期间发生。当一个对象的析构函数被调用时,它会调用该对象所有数据成员的析构函数,而后者又会调用其对象所有数据成员的析构函数,以此类推。【参考方案2】:

这是错误的:

MessageForwarder::~MessageForwarder()

    delete &this->monitor;
    delete &this->myName;
    delete &this->myAddress;
    fprintf(stdout, "Cleaning up MessageForwarder\n");

包含的成员对象的析构函数会自动插入到包含类的析构函数中。此外,你没有new他们,是吗,那为什么delete

【讨论】:

【参考方案3】:

free()malloc() 中的段错误通常意味着您已经以某种方式破坏了堆,或者通过多次释放某些东西,或者释放从未分配过的东西。实际的错误几乎永远不会发生在段错误发生的地方。

正如其他人指出的那样,您的错误是 deleteing string 您班级的成员。这些成员的内存(忽略它们可能在内部动态分配的任何内存)不是通过单独调用 malloc/new 分配的,因此当您释放它们时,您会弄乱堆。正如@Nikolai 指出的那样,他们适当的析构函数是自动运行的。

但是,如果您声明了以下内容:

class Foo 
    string *s1;
;

那么你需要在 Foo 的析构函数中 delete this-&gt;s1

【讨论】:

以上是关于删除对象时出现段错误 - GDB 在 free() 中说的主要内容,如果未能解决你的问题,请参考以下文章

尝试访问向量中对象中的字段时出现段错误

关闭文件时出现段错误

分配结构数组时出现段错误

尝试访问二维向量元素时出现段错误

通过指针调用方法时出现段错误

在 openCV 中将 cvPoint[][] 转换为 cvPoint** 时出现段错误