malloc.c:3097:sYSMALLOc:断言在动态创建的对象的构造函数内部失败

时间:2012-02-13 23:21:53

标签: c++ oop malloc

我对使用C ++的OOP有些新意,所以我希望我刚刚犯了一些简单的初学者错误。我有一些代码给了我看似无法解释的malloc错误。我已经将代码减少到仍然崩溃的最小的东西,这就是:

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

我正在编译:

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

当我运行它时,我得到了这个:

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

我见过valgrind建议调试这类问题的工具,我无法从它的输出中理解任何东西。输出很长,所以我粘贴了它here

Gdb指向创建新向量的行是问题(这并不太令人惊讶)。完整的gdb输出为here。我觉得奇怪的是,如果我不访问任何一个字符串长度,那么创建新的向量没有问题。

我真的很茫然,任何帮助都会非常感激!

2 个答案:

答案 0 :(得分:3)

主要问题是您以两种不兼容的方式定义了MyClass:在MyClass.cpp中,它有五个数据成员(两个指针,两个整数和另一个指针),但在{{ 1}},因此在MyClass.h中,它根本没有数据成员。因此,当您的test.cpp函数调用main时,系统仅为{-1}}的无数据成员版本分配足够的内存,然后调用构造函数,该构造函数初始化数据成员你没有为。分配内存。

您需要将班级定义从new MyClass(A, B)移至MyClassMyClass.cpp的第一行应为MyClass.h。这将确保您没有任何不兼容性,因为如果您这样做,将导致MyClass.cpp发出编译错误。

答案 1 :(得分:1)

您已宣布两个完全不同的MyClass版本;一个位于MyClass.h,另一个位于MyClass.cppmain()中的test.cpp函数可以看到MyClass.h中的版本,并根据该定义分配内存,但MyClass.cpp中的代码是在不同的类定义上运行的。

失败的原因是因为这两个定义在内存中具有不同的大小和布局。

要正确执行此操作,您需要在MyClass.h中包含MyClass的完整定义。 即。

#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

这是C ++的关键点之一 - 即使是私有成员也需要在公共可访问的类定义中。

然后,您需要在MyClass.h以及MyClass.cpp中加入test.cpp,并从MyClass中删除MyClass.cpp的声明 - 您只需要类声明出现在一个地方。


你也有内存泄漏,因为你没有给MyClass一个析构函数,它会清理它在构造函数中分配的内存。在整个地方编写newdelete的更好方法是调查std::shared_ptr