删除对象时出现段错误 - 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()
中的段错误通常意味着您已经以某种方式破坏了堆,或者通过多次释放某些东西,或者释放从未分配过的东西。实际的错误几乎永远不会发生在段错误发生的地方。
正如其他人指出的那样,您的错误是 delete
ing string
您班级的成员。这些成员的内存(忽略它们可能在内部动态分配的任何内存)不是通过单独调用 malloc/new 分配的,因此当您释放它们时,您会弄乱堆。正如@Nikolai 指出的那样,他们适当的析构函数是自动运行的。
但是,如果您声明了以下内容:
class Foo
string *s1;
;
那么你需要在 Foo 的析构函数中 delete this->s1
。
【讨论】:
以上是关于删除对象时出现段错误 - GDB 在 free() 中说的主要内容,如果未能解决你的问题,请参考以下文章