Утечка памяти или ошибка памяти при попытке обработки вложенных объектов / структур и динамических массивов.Возможная проблема Xcode / malloc - PullRequest
1 голос
/ 18 июля 2011

Когда я компилирую с Xcode и запускаю это, я получаю ошибку, по крайней мере, 100 раз подряд, malloc: *** error for object 0x100180: double free, с отладчиком, указывающим на line C. Как ни странно, в коде, из которого я это извлек, возникает та же самая ошибка, но отладчик указывает на эквивалент line B. Я пытался, но не смог воспроизвести это.

Если я удаляю line A, код работает, но я получаю серьезную утечку памяти, которая приводит к сбою программы примерно через 1 минуту. Удаление line C решает проблему, но не является правильным решением, потому что тогда a_class не имеет надлежащего деструктора.

#include <iostream>
#include <vector>

struct a_struct
{
    int* dynamic_array;
    a_struct(int length) {dynamic_array = new int [length];}
    a_struct() : dynamic_array(NULL) {}
    ~a_struct() { if (dynamic_array != NULL) {delete [] dynamic_array;} }  //Line A
};

class a_class
    {
    public:
        a_struct* the_structs;
        a_class() {Init();}
        a_class(a_class const & origin) {Init();}
        void Init(){
            the_structs = new a_struct [10];                              //Line B 
            for(int q=0; q<10; q++)
                the_structs[q] = a_struct(7);}
        ~a_class() { if (the_structs != NULL) {delete [] the_structs;} }  //Line C
    };

int main () 
{
    std::vector <a_class> the_objects;
    for(int q=0; q<10; q++)
        the_objects.push_back(a_class());

    while(1)
        for(int q=0; q <10; q++)
            for(int w=0; w <10; w++)
                the_objects[q].the_structs[w] = a_struct(7);
}

Ответы [ 4 ]

4 голосов
/ 18 июля 2011

Исправьте a_struct и a_class, чтобы иметь правильные конструкторы копирования и операторы присваивания. Тогда возвращайся, если проблема все еще есть.

Убедитесь, что все ваши классы всегда соблюдают Правило 3 . Кажется, в последнее время я часто ссылаюсь на эту страницу.

2 голосов
/ 18 июля 2011

Проблема в том, что вы пытаетесь сделать свое собственное управление памятью.

Используйте встроенные контейнеры:

struct a_struct
{
    std::vector<int>    dynamic_array;
    a_struct(int length) : dynamic_array(length){}
    a_struct()           : dynamic_array() {}
};

class a_class
{
    public:
        std::vector<a_struct>   the_structs;
        a_class()                       {Init();}
        a_class(a_class const & origin) {Init();}
        void Init()
        {
            the_structs.resize(10); 
            for(int q=0; q<10; q++)
                the_structs[q] = a_struct(7);
        }
};
0 голосов
/ 18 июля 2011

Проблема в том, что неявно сгенерированный конструктор копирования в a_struct не выполняет глубокое копирование, но деструктор всегда предполагает, что память была выделена для каждого экземпляра.Вам нужно создать конструктор копирования для него, который делает глубинную копию.Но лучше использовать просто std::vector вместо нового и удалить.Тогда вам не нужно беспокоиться о том, чтобы все ваши конструкторы были правильными.

Кроме того, конструктор копирования для a_class фактически не копирует объект.Это почти наверняка вызовет проблемы в будущем, когда он не поддерживает ожидаемую семантику копирования.

0 голосов
/ 18 июля 2011

Проблема в том, что a_struct не имеет правильного конструктора копирования и operator =.Из-за этого одновременно два a_struct::dynamic_array указывают на одну и ту же область памяти, и оба будут вызывать delete[] dynamic_array; в деструкторе.Следовательно, double delete .

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

В вашем случае вы можете изменить определение следующим образом:

struct a_struct
{
  int length_;  //<<--- add this for record
  int* dynamic_array;
  a_struct(int length) : length_(length) {dynamic_array = new int [length_]; }
  a_struct() : dynamic_array(NULL) {}
  a_struct(const a_struct &copy)  // <<--- copy ctor
  {
    do_copy(copy);
  }
  a_struct& operator = (const a_struct &copy)  // <<--- assignment operator
  {
    delete[] dynamic_array; // clear earlier array
    do_copy(copy);
    return *this;
  }
  ~a_struct() { if (dynamic_array != NULL) {delete [] dynamic_array;} }  //Line A

  void do_copy (const a_struct &copy)
  {
    // do necessary null checks for "copy"
    dynamic_array = new int[length_ = copy.length];
    memcpy(dynamic_array, copy.dynamic_array, length_);
  }
};

Те же меры предосторожности вы принимаете для любоготакие class.

...