views:

173

answers:

3

I am working on an assignment for networking where we are supposed to create a networking library in C and then use it in our C++ program. My C++ isn't as strong as my C so I got started on that first so I could tackle any problems that came up, and I present you my first one. :D

I have a base class and an inherited class (there will eventually be another inherited one) which will provide functions that determine the servers behavior.

Base Class header and destructor:

    // 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");
}

Inherited Class and destructor:

// 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");
}

My problem arises when I try to delete a class object. My program follows this:

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;}

When I go ahead and run my program it segfaults on the line delete msgFrwder; I go ahead and use GDB with the dumped core and ask where it happens and it gives me the following:

#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

With my limited C++ knowledge I feel like I am following the proper steps to clean up and free my memory. When I run my program it does in fact output "Cleaning up MessageForwarder" so I know it executed that line.

I have searched for solution and struggled with the problem for a while but can't find a solution. Any help would be much appreciated or an explanation of what is actually going on and why the segfault is happening would help.

Thanks for all your help. Its appreciated. :D

+3  A: 

string objects were not allocated using new operator. Do not delete them, they will be freed automatically

aaa
So I can only delete objects that I create with new then? And as far as them being freed automatically that just happens upon exiting the program or when the class destructor is called?
Chris
@Chris basically what happens is that destructor for each member variable is called by the object destructor, negating the need to explicitly destruct (unless you use raw pointers). In general yes, delete does with new, but be careful where you use new[], because then you have to use delete[]
aaa
@Chris: The general rule is that - whatever brought it into being (malloc, new, new[], implicitly via the stack) - you must use the opposite (free, delete, delete[], implicitly via the stack).
crazyscot
@Chris: It will happen during the destruction of `MessageForwarder`. When the destructor of an object is called, it will call the destructors of all of that object's data members, which will in turn call the destructors of all of their objects' data members, and so on.
Josh Townzen
+2  A: 
Nikolai N Fetissov
A: 

A segfault within free() or malloc() usually means that you've corrupted the heap somehow, either by freeing something more than once, or freeing something that was never allocated. The actual bug is almost never where the segfault occurs.

Your error, as others have pointed out, is deleteing the string members of your class. The memory for those members (ignoring any memory they might dynamically allocate internally) was not allocated by a separate call to malloc/new, and so when you free them you mess up the heap. As @Nikolai points out, they appropriate destructor is run automatically.

However, if you had declared the following:

class Foo {
    string *s1;
};

then you would need to delete this->s1 in Foo's destructor.

Dale Hagglund