Как удалить переменную-член, состоящую из массива указателей - PullRequest
0 голосов
/ 16 февраля 2011

Добрый день, я пытаюсь удалить переменную-член класса C ++, состоящую из массива указателей. Вот выдержка из кода:

class NFA {
public:

    dict<tuple2<__ss_int, __ss_int> *, dict<str *, __shedskin__::set<tuple2<__ss_int, __ss_int> *> *> *> *transitions;

    auto_vector< dict<str *, set<tuple2<__ss_int, __ss_int> *> *> >   *tmpautovector;

    NFA() {} 
    ~NFA() { delete this->tmpautovector
    NFA(tuple2<__ss_int, __ss_int> *start_state) {
        this->__class__ = cl_NFA;
        __init__(start_state);
    }
    void *add_transition(tuple2<__ss_int, __ss_int> *src, str *input, tuple2<__ss_int, __ss_int> *dest);
}


void *NFA::add_transition(tuple2<__ss_int, __ss_int> *src, str *input, tuple2<__ss_int, __ss_int> *dest) {
     dict<str *, set<tuple2<__ss_int, __ss_int> *> *> *tmpdict;

    if ((!(this->transitions)->__contains__(src))) {
        tmpdict = new dict<str *, set<tuple2<__ss_int, __ss_int> *> *>();
        this->transitions->__setitem__(src, tmpdict);
        tmpautovector->push_back(tmpdict);
    }
    return NULL;
}

Я пытаюсь использовать класс auto_vector для хранения массива указателей. Вот некоторые функции класса auto_vector. В документации этого класса говорится, что это не STL-вектор auto_ptr. Использование векторов STL для хранения auto_ptr настоятельно не рекомендуется> Я продолжаю получать ошибку сегментации, когда получаю доступ к функции auto_vector :: operator-член> Трассировка стека GDB, показанная ниже, показывает ошибку сегментации. Мне интересно, можно ли исправить эту ошибку сегментации или есть ли лучший подход к удалению переменных-членов, состоящих из массива указателей. Спасибо.

// auto_vector.h
// This file is (C) 2002-2004 Royce Mitchell III
// and released under the LGPL & BSD licenses

#ifndef AUTO_VECTOR_H
#define AUTO_VECTOR_H

#include <sys/types.h>
#include <memory>




template<class T>
class auto_vector
{
public:
    explicit auto_vector ( size_t capacity = 0 )
        : _arr(0), _capacity(0), _end(0)
    {
        if ( capacity != 0 )
            _arr =  new std::auto_ptr<T>[capacity];
        _capacity = capacity;
    }

    ~auto_vector()
    {
        delete []_arr;
    }

    size_t size() const
    {
        return _end;
    }

    const std::auto_ptr<T>& operator [] ( size_t i ) 
        {
        return _arr[i];
    }

    std::auto_ptr<T>& operator [] ( size_t i )
        {
        return _arr[i];
    }

        void push_back ( std::auto_ptr<T>& p )
    {
        reserve ( _end + 1 );
        _arr[_end++] = p;
    }

        void push_back ( T * p )
    {
        reserve ( _end + 1 );
        std::auto_ptr<T> tmp(p);
        _arr[_end++] = tmp;
        //GCC is pedantic, this is an error.
        //_arr[_end++] = auto_ptr<T>(p);
    }

    void reserve ( size_t reqCapacity )
    {
        if ( reqCapacity <= _capacity )
            return;
        size_t newCapacity = 2 * _capacity;
        if ( reqCapacity > newCapacity )
            newCapacity = reqCapacity;
        // allocate new array
        std::auto_ptr<T> * arrNew = new std::auto_ptr<T> [newCapacity];
        // transfer all entries
        for ( size_t i = 0; i < _capacity; ++i )
            arrNew[i] = _arr[i];
        _capacity = newCapacity;
        // free old memory
        delete[] _arr;
        // substitute new array for old array
        _arr = arrNew;
    }

private:
    std::auto_ptr<T>  *_arr;
    size_t        _capacity;
    size_t        _end;
};

#endif//AUTO_VECTOR_H

Program received signal SIGSEGV, Segmentation fault.
0x0806b85a in std::auto_ptr<__shedskin__::setentry<__shedskin__::tuple2<int, int>*> >::get (this=0x0)
    at /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/memory:300
300           get() const throw() { return _M_ptr; }
(gdb) bt
#0  0x0806b85a in std::auto_ptr<__shedskin__::setentry<__shedskin__::tuple2<int, int>*> >::get (this=0x0)
    at /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/memory:300
#1  0x0806be61 in __shedskin__::set<__shedskin__::tuple2<int, int>*>::lookup (this=0x80a3c58, key=0x80a3c40, 
    hash=-1919631394) at ../Include/builtin.hpp:3223
#2  0x0806bfc7 in __shedskin__::set<__shedskin__::tuple2<int, int>*>::insert_key (this=0x80a3c58, key=0x80a3c40, 
    hash=-1919631394) at ../Include/builtin.hpp:3258
#3  0x080728ea in __shedskin__::set<__shedskin__::tuple2<int, int>*>::add (this=0x80a3c58, key=0x80a3c40)
    at ../Include/builtin.hpp:3278
#4  0x0806af0c in main (Argc_=<value optimized out>, Argv_=<value optimized out>) at ../Source/mdMatchupTest.cpp:93
(gdb) frame 1
#1  0x0806be61 in __shedskin__::set<__shedskin__::tuple2<int, int>*>::lookup (this=0x80a3c58, key=0x80a3c40, 
    hash=-1919631394) at ../Include/builtin.hpp:3223
3223        setentry<T>* entry = table->operator[](i)->get(); // &table[i]

Ответы [ 2 ]

3 голосов
/ 16 февраля 2011

У меня такое ощущение, что авторы NFA и auto_vector здесь что-то не так.Почему члены указатели?Вы должны воспользоваться RAII;Именно здесь C ++ превосходит другие языки!У вас есть гарантия, что, когда действительный автоматический объект выйдет из области видимости, будет вызван его деструктор, независимо от того, перемотан ли стек из-за исключения или стек разворачивается корректно.Воспользуйтесь этой гарантией!

Для начала, выбросьте этот aut_vector класс.Тебе это не нужно.Используйте std::vector<boost::shared_ptr<T> >.Как автоматический член, а не член-указатель, конечно.Затем удалите деструктор;вам это не нужно.

Там вы устранили полноценный класс и деструктора.Если бы у вас был конструктор копирования, который у вас должен был быть, и оператор присваивания, который у вас тоже должен был быть, и элемент подкачки, который был бы отличной идеей, то вы могли бы их тоже устранить.Это устраняет много кода и много правильности.Две птицы, один камень.

0 голосов
/ 18 февраля 2011
I have solved the segmentation fault problem. It occured when memory allocated with malloc was deallocated with delete, thereby corrupting the heap. I replaced all the malloc's with the new operator. The reason the malloc was mismatched with delete was because the python to C++ converter program used the Boehm garbage collector. We are taking out the Boehm garbage collector and replacing it with new and delete. The Boehm garbage collector has two disadvantages, First, it pauses at random  times during garbage collection. Second, it has a finite amount of heap memory which can only be changed at compile time. As a result, it has scalability issues with large applications.
The auto_vector class runs Okay. I tested it with Valgrind and there were no major problems. The memory leak has been addressed. Thank you for all the Boost suggestions. 
...