开发者

How to delete an member variable consisting of an array of pointers

Good afternoon, I am trying to delete a C++ class member variable consisting of an array of pointers. Here is an excerpt of the code:

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

I am trying to use the auto_vector class to store an array of pointers. Here are some of the functions of the auto_vector class. The documentation for this class says that this is not a STL vector of auto_ptr's . The use of STL vectors to store auto_ptr's is strongly discouraged > I keep getting a segmentation fault when I access the auto_vector::operator member function > The GDB stack trace, shown below shows the segmentation fault. I am wondering whether it is possible to fix this segmentation fault or whether are better approaches to deleting member variables consisting of array of pointers. Thank you.

// 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>&开发者_JAVA百科amp; 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]


I have a feeling the authors of NFA and auto_vector are getting something wrong here. Why are the members pointers? You should take advantage of RAII; this is precisely where C++ excels over other languages! You have the guarantee that when a valid automatic object goes out of scope its destructor will be called, regardless of wether the stack rewinds due to an exception or the stack unrolls cleanly. Take advantage of this guarantee!

For starters, throw away that aut_vector class. You don't need it. Use a std::vector<boost::shared_ptr<T> >. As an automatic member, not a pointer member, of course. Then remove the destructor; you don't need it.

There, you eliminated a full-blown class and a destructor. If you had a copy-constructor, which you should have had, and an assignment operator, which you should have had as well, and a swap member, which would have been an excellent idea to have, then you could eliminate these too. That's a lot of code eliminated and a lot of correctness achieved. Two birds, one stone.


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. 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜