Gordon Bailey
Gordon Bailey

Reputation: 3911

malloc.c:3097: sYSMALLOc: Assertion fails inside constructor of dynamically created object

I'm somewhat new to OOP with C++, so I'm hoping that I've just made some simple beginner mistake. I've got some code that is giving me seemingly inexplicable malloc errors. I've reduced my code to the smallest thing that still crashes, which is this:

MyClass.cpp:

#include <vector>
using std::vector;

#include <string>
using std::string;

class MyClass{
      string * myString1;
      string * myString2;

      int length1;
      int length2;

      vector< vector<int>* > * myVector;

   public:
      MyClass(string * a, string * b);
};

MyClass::MyClass(string * a, string * b)
: myString1(a), myString2(b)
{

   // commenting both of the lines that access the string sizes
   // makes it work

   length1 = myString1->size();

   // commenting either or both of the following lines makes
   // it work

   length2 = myString2->size();

   myVector = new vector< vector<int>* >;
}

MyClass.h

#ifndef MyClass_H
#define MyClass_H

#include <string>
using std::string;

class MyClass{
   public:
      MyClass(string * a, string * b);
};

#endif

test.cpp:

#include "../include/MyClass.h"
#include <string>
using std::string;


int main()
{
   string * A = new string("foobar");
   string * B = new string("foobaz");

   MyClass * mc = new MyClass(A, B);

   return 0;
}

I'm compiling like this:

g++ -ggdb -Wall -c src/test.cpp -o .objects/test.o
g++ -ggdb -Wall -c src/MyClass.cpp -o .objects/MyClass.o
g++ .objects/test.o .objects/MyClass.o  -ggdb -Wall -o test

And when I run it I get this:

test: malloc.c:3097: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Aborted

I've seen valgrind suggested as a tool to debug these kinds of problems, I wasn't able to understand anything from it's output. The output is quite long, so I've pasted it here.

Gdb points to the line where the new vector is created as being the problem (which is not too surprising). The full gdb output is here. What I find odd is that If I don't access either of the string lengths, then the new vector is created with no problem.

I'm really at a loss here, any help would be greatly appreciated!

Upvotes: 1

Views: 1719

Answers (2)

aalpern
aalpern

Reputation: 662

You've declared two completely different versions of MyClass; one in MyClass.h, and the other in MyClass.cpp. Your main() function in test.cpp sees the version from MyClass.h, and will allocate memory according to that definition, but your code in MyClass.cpp is operating on a different definition of the class.

The reason this is failing is because those two definitions have different sizes and layouts in memory.

To do this properly, you need to include the complete definition of MyClass in MyClass.h. i.e.

#ifndef MyClass_H
#define MyClass_H

#include <string>
using std::string;

class MyClass {
      string * myString1;
      string * myString2;
      int length1;
      int length2;
      vector< vector<int>* > * myVector;
   public:
      MyClass(string * a, string * b);
};

#endif

This is one of the key points of C++ - even the private members need to be in the publicly accessible definition of the class.

Then you need to include MyClass.h in MyClass.cpp as well as in test.cpp, and remove the declaration of MyClass from MyClass.cpp -- you only want the class declaration to appear in one place.


You also have a memory leak, because you haven't given MyClass a destructor where it will clean up the memory it has allocated in its constructor. A better approach to writing new and delete all over the place would be to investigate std::shared_ptr.

Upvotes: 1

ruakh
ruakh

Reputation: 183484

The major problem is that you've defined MyClass in two incompatible ways: in MyClass.cpp, it has five data members (two pointers, two integers, and another pointer), but in MyClass.h, and therefore in test.cpp, it has no data members at all. Therefore, when your main function calls new MyClass(A, B), the system allocates only enough memory for the no-data-members version of MyClass, and then it invokes the constructor, which initializes data members that you didn't allocate memory for.

You need to move your class definition from MyClass.cpp to MyClass.h, and the very first line of MyClass.cpp should be #include "MyClass.h". This will ensure that you don't have any incompatibilities, since it will cause MyClass.cpp to emit a compile error if you do.

Upvotes: 3

Related Questions