Деструктор, кажется, называется «рано» - PullRequest
2 голосов
/ 29 декабря 2010

Оказалось, что это была простая проблема с использованием конструктора. Пожалуйста, смотрите обновленную информацию в разделе "edit".

Извините за еще один вопрос о C ++ dtor ... Однако я не могу найти такой же, как мой, как все остальныеназначаем контейнеры STL (которые будут сами удалять объекты), а мои - массиву указателей.

Итак, у меня есть следующий фрагмент кода

#include<iostream>

class Block{
public:
    int x, y, z;
    int type;
    Block(){
        x=1;
        y=2;
        z=3;
        type=-1;
    }
};

template <class T> class Octree{
    T* children[8];
public:
    ~Octree(){
        for( int i=0; i<8; i++){
            std::cout << "del:" << i << std::endl;
            delete children[i];
        }
    }    
    Octree(){
        for( int i=0; i<8; i++ )
            children[i] = new T;
    }
    // place newchild in array at [i]
    void set_child(int i, T* newchild){
        children[i] = newchild;
    }
    // return child at [i]
    T* get_child(int i){
        return children[i];
    }
    // place newchild at [i] and return the old [i]
    T* swap_child(int i, T* newchild){
        T* p = children[i];
        children[i] = newchild;
        return p;
    }
};

int main(){
    Octree< Octree<Block> > here;
    std::cout << "nothing seems to have broken" << std::endl;
}

Просматривая вывод, я замечаю, чтодеструктор вызывается много раз, прежде чем я думаю, что он должен (поскольку Октри все еще находится в области видимости), конец вывода также показывает:

del:0
del:0
del:1
del:2
del:3

Process returned -1073741819 (0xC0000005)   execution time : 1.685 s
Press any key to continue.

По какой-то причине деструктор проходит через ту же точку вцикл дважды (0), а затем умирает.

Все это происходит до того, как «ничего не пошло не так», как я ожидал до вызова любого dtor.

Заранее спасибо:)

РЕДАКТИРОВАТЬ В коде, который я разместил, были удалены некоторые вещи, которые я считал ненужными, но после копирования и компиляции кода, который я вставил, я больше не получаюROR.Я удалил другие целочисленные атрибуты кода.Вот оригинал:

#include<iostream>

class Block{
public:
    int x, y, z;
    int type;
    Block(){
        x=1;
        y=2;
        z=3;
        type=-1;
    }
    Block(int xx, int yy, int zz, int ty){
        x=xx;
        y=yy;
        z=zz;
        type=ty;
    }
    Block(int xx, int yy, int zz){
        x=xx;
        y=yy;
        z=zz;
        type=0;
    }
};

template <class T> class Octree{
    int x, y, z;
    int size;
    T* children[8];
public:
    ~Octree(){
        for( int i=0; i<8; i++){
            std::cout << "del:" << i << std::endl;
            delete children[i];
        }
    }

    Octree(int xx, int yy, int zz, int size){
        x=xx;
        y=yy;
        z=zz;
        size=size;
        for( int i=0; i<8; i++ )
            children[i] = new T;
    }
    Octree(){
        Octree(0, 0, 0, 10);
    }
    // place newchild in array at [i]
    void set_child(int i, T* newchild){
        children[i] = newchild;
    }
    // return child at [i]
    T* get_child(int i){
        return children[i];
    }
    // place newchild at [i] and return the old [i]
    T* swap_child(int i, T* newchild){
        T* p = children[i];
        children[i] = newchild;
        return p;
    }
};

int main(){
    Octree< Octree<Block> > here;
    std::cout << "nothing seems to have broken" << std::endl;
}

Также, что касается проблем с set_child, get_child и swap_child, приводящих к возможным утечкам памяти, это будет решено, так как класс-оболочка будет либо использовать get перед set, либо использовать swap для получениястарый ребенок и запишите это на диск перед тем, как освободить саму память.

Я рад, что это не мое управление памятью, а скорее другая ошибка.Я еще не сделал оператор копирования и / или назначения, так как я только что тестировал дерево блоков, я почти наверняка сделаю их все очень частными очень скоро.

Эта версия выплевывает -1073741819.

Спасибо всем за ваши предложения, и я приношу извинения за то, что похитил мой собственный поток: $

решено Проблема с одним конструктором, вызывающим другого.

Спасибо всем за вашу помощь иизвиняюсь за потраченное время :))

Ответы [ 5 ]

6 голосов
/ 29 декабря 2010

Кто-то определил конструктор и деструктор, но не конструктор копирования. Это уничтоженные копии, которые портят счет. Следуйте правилу трех .

3 голосов
/ 29 декабря 2010

Проблема с конструктором по умолчанию (который вы не добавляли до редактирования!); он создает временный экземпляр Octree, где, я думаю, вы подумали, что он просто вызовет другой конструктор:

Octree(){
    Octree(0, 0, 0, 10);
}

Именно этот экземпляр вы видите разрушенным до крушения. Затем вы пытаетесь удалить некоторые children, которые никогда не были new ed (или инициализированы).

Извлечение кода инициализации из Octree(int, int, int, int ) в метод решит вашу проблему. Например:

Octree(int xx, int yy, int zz, int size){
    init(xx, yy, zz, size);
}
Octree(){
    init(0, 0, 0, 10);
}

void init(int xx, int yy, int zz, int)
{
    x=xx;
    y=yy;
    z=zz;
    for( int i=0; i<8; i++ )
        children[i] = new T;

}

Либо удалите ваш конструктор по умолчанию и добавьте значения по умолчанию для каждого аргумента в оставшийся конструктор:

Octree(int xx = 0, int yy = 0, int zz = 0, int size = 10)
    :x(xx)
    ,y(yy)
    ,z(zz)
    ,size(size)
{
    for( int i=0; i<8; i++ )
        children[i] = new T;
}

Тем не менее, действительно , действительно нужно работать с необработанными указателями? Если вы это сделаете, то вам почти наверняка нужно что-то сделать , чтобы скопировать , прежде чем ваш класс будет полезен.

В ответ на ваш следующий вопрос, «Нет!» «только до C ++ 11!»

In (и его преемники):

Вы можете теперь делегировать конструкцию, но синтаксис немного отличается от того, как вы пытались выразить это:

Octree()
    :Octree(0, 0, 0, 10)
{
}
3 голосов
/ 29 декабря 2010

Это не проходит через один и тот же цикл дважды. У вашего высшего уровня Octtree есть 8 дочерних Octrees, поэтому вы видите вложенное разрушение. Я не уверен, почему это умирает все же.

1 голос
/ 29 декабря 2010

Вальгринд сказал:

==11907== HEAP SUMMARY:
==11907==     in use at exit: 0 bytes in 0 blocks
==11907==   total heap usage: 72 allocs, 72 frees, 1,536 bytes allocated
==11907== 
==11907== All heap blocks were freed -- no leaks are possible
1 голос
/ 29 декабря 2010

Я подозреваю, что вы просто завершили уничтожение, и программа завершилась до того, как весь вывод был записан на консоль.Ожидается, что эта штука дважды проходит через 0, так как это Octree<> 0, а затем Octree<Octree<>> 0.

. Вам нужно изменить код, чтобы гарантировать, что деструкторы работают, И чтобы все консольные I /O выполняется перед завершением процесса.

int main(){
 {
  Octree< Octree<Block> > here;
 }
 std::cout << "nothing seems to have broken" << std::endl;
 std::cin.get();
}

Конечно, этот код имеет множество ДРУГИХ недостатков.Но я начну с конкретной проблемы.

...