malloc.c: 3097: sYSMALLOc: сбой утверждения внутри конструктора динамически создаваемого объекта - PullRequest
1 голос
/ 14 февраля 2012

Я немного новичок в ООП с C ++, так что я надеюсь, что я только что сделал какую-то простую ошибку новичка.У меня есть код, который дает мне, казалось бы, необъяснимые ошибки 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 предложил в качестве инструмента для устранения подобных проблем, я не смог ничего понять из его результатов.Вывод довольно длинный, поэтому я вставил его здесь .

Gdb указывает на линию, где новый вектор создается как проблема (что не так уж удивительно).Полный вывод GDB здесь .Что мне показалось странным, так это то, что если я не получу доступ ни к одной из длин строк, то новый вектор будет создан без проблем.

Я действительно в растерянности, любая помощь будет принята с благодарностью!

Ответы [ 2 ]

3 голосов
/ 14 февраля 2012

Основная проблема в том, что вы определили MyClass двумя несовместимыми способами: в MyClass.cpp он имеет пять элементов данных (два указателя, два целых числа и другой указатель), но в MyClass.h, и, следовательно,в test.cpp он вообще не имеет элементов данных.Поэтому, когда ваша main функция вызывает new MyClass(A, B), система выделяет только достаточно памяти для версии MyClass без элементов данных, а затем вызывает конструктор, который инициализирует элементы данных, которые вы не выделяли в памятиfor.

Вам нужно переместить определение класса с MyClass.cpp на MyClass.h, а самая первая строка MyClass.cpp должна быть #include "MyClass.h".Это обеспечит отсутствие несовместимости, поскольку в этом случае MyClass.cpp выдаст ошибку компиляции.

1 голос
/ 14 февраля 2012

Вы объявили две совершенно разные версии MyClass; один в MyClass.h, а другой в MyClass.cpp. Ваша main() функция в test.cpp видит версию из MyClass.h и будет выделять память в соответствии с этим определением, но ваш код в MyClass.cpp работает с другим определением класса.

Причина, по которой это не удается, заключается в том, что эти два определения имеют разные размеры и макеты в памяти.

Чтобы сделать это правильно, вам нужно включить полное определение MyClass в MyClass.h. т.е.

#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 деструктор, который будет очищать память, выделенную в его конструкторе. Лучшим подходом к написанию new и delete повсюду было бы исследование std :: shared_ptr .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...