如何删除由指针数组组成的成员变量

时间:2011-02-15 21:50:22

标签: c++ gcc memory-leaks

下午好,我正在尝试删除由指针数组组成的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类的一些功能。这个类的文档说这不是auto_ptr的STL向量。强烈建议不要使用STL向量来存储auto_ptr。当我访问auto_vector :: operator member function&gt;时,我一直遇到分段错误。 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 个答案:

答案 0 :(得分:3)

我有一种感觉NFAauto_vector的作者在这里弄错了。为什么成员指针?你应该利用RAII;这正是C ++优于其他语言的地方!您可以保证当有效的自动对象超出范围时,将调用其析构函数,无论堆栈是否由于异常或堆栈完全展开而重新启动。利用这个保证!

对于初学者,扔掉aut_vector课程。你不需要它。使用std::vector<boost::shared_ptr<T> >。当然,作为自动成员,不是指针成员。然后删除析构函数;你不需要它。

在那里,你删除了一个完整的和一个析构函数。如果你有一个你应该拥有的复制构造函数,以及你应该拥有的赋值运算符,以及交换成员,这本来是一个很好的主意,那么你也可以消除它们。这消除了很多代码并且实现了很多正确性。两只鸟,一石。

答案 1 :(得分:0)

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.