构造函数中的分段错误不明确

时间:2011-09-10 20:49:59

标签: c++ segmentation-fault

我为矩阵对象构建了一个构造函数。数据存储在struct val数组中,而struct SparseMatrix::SparseMatrix(const int numRow, const int numCol, vector<double> fill): Matrix(numRow,numCol) { _matrix = new vector<val*>(fill.size()); vector<double>::iterator itr = fill.begin(); for(signed int i=0; i<numRow; i++) { for(signed int j=0; j<numCol; j++, itr++) { if (*itr == 0) { continue; } val *temp = new val; temp->value = *itr; temp->x = i; temp->y = j; _matrix->push_back(temp); cout << "Psition: " << ": " << _matrix->front()->x << //<--ERROR cout << " " << _matrix->back()->y << endl; } } } 则保持位置(在矩阵中)和值。这是代码:

==13334== Invalid read of size 4
==13334==    at 0x804AEAE: SparseMatrix::SparseMatrix(int, int, std::vector<double,     std::allocator<double> >) (in /home/yotamoo/workspace/ex3/main)
==13334==    by 0x8048C10: main (in /home/yotamoo/workspace/ex3/main)
==13334==  Address 0x8 is not stack'd, malloc'd or (recently) free'd
==13334== 
==13334== 
==13334== Process terminating with default action of signal 11 (SIGSEGV)
==13334==  Access not within mapped region at address 0x8
==13334==    at 0x804AEAE: SparseMatrix::SparseMatrix(int, int, std::vector<double,     std::allocator<double> >) (in /home/yotamoo/workspace/ex3/main)
==13334==    by 0x8048C10: main (in /home/yotamoo/workspace/ex3/main)
==13334==  If you believe this happened as a result of a stack
==13334==  overflow in your program's main thread (unlikely but
==13334==  possible), you can try to increase the size of the
==13334==  main thread stack using the --main-stacksize= flag.
==13334==  The main thread stack size used in this run was 8388608.

你会注意到我添加了cout只是为了验证push_back对我来说真的不起作用。 _matrix在堆上,所有结构都在其中。全部使用'new'创建。我不明白为什么这不起作用。我将一个新的结构指针推向向量后的一行我无法读取它(我说的是分段错误)。

有什么想法吗?谢谢!

编辑: 对不起,这是valgrind的消息:

{{1}}

并且 - 在第一次迭代期间发生分段错误!

3 个答案:

答案 0 :(得分:4)

这是用于构建std::vector<val *>的{​​{1}}构造函数:

*_matrix

调用explicit vector ( size_type n, const val *& value = val *(), const std::allocator<val *>& = std::allocator<val *>() ); 设置为n的构造函数会创建一个新的fill.size() std::vector<val *>默认构造的fill.size()个对象(所有val * })。当您推回新的NULL指针时,val*_matrix个元素,而fill.size() + 1仍然是_matrix->front()指针。实际上,您正在取消引用NULL

您可能正在寻找reserve()方法。

编辑:我注意到还有其他一些可以改进的事情:

  1. NULL构造函数按值SparseMatrix。这意味着为了构造新的fill,可以生成SparseMatrix个对象的完整副本。您应该通过const-reference传递double
  2. 使用STL容器迭代器,除非您需要后增量的结果,否则应始终使用预增量运算符。
  3. 如果新fill对象的某个分配引发val异常,那么您将泄漏内存。
  4. 考虑使用池分配器来分配许多std::bad_alloc个对象。一些C / C ++运行时库实现(例如OpenBSD)随机化内存分配。在堆上分配许多小对象可能会导致严重的堆碎片。

答案 1 :(得分:2)

如果numCol&gt; fill.size(),你的循环将结束。

答案 2 :(得分:0)

正如其他人所解释的那样,错误是您使用nullptrs初始化而不是保留然后取消引用它们。

您还为所有项目预留空间,而不是释放未使用的空间。您的稀疏数组将始终使用比传入的原始矢量更多的空间。

你不应该批评所有这些项目。使用值向量。这将使您的代码异常安全。

还有一个问题是您没有检查您是否有权填写。至少应该对元素的数量有一个断言。

假设val是这样的结构:

struct val
{
     val( int x, int y, double value ):x(x),y(y),value(value){}
     int x;
     int y;
     double value;
};

然后改进/更正的版本可能如下所示:

class SparseMatrix
{
   vector<val> _matrix;

public:

    SparseMatrix(const int numRow, const int numCol, vector<double> const& fill)
    {
        assert( numCol > 0 );
        assert( numRow > 0 );
        assert( numRow * numCol == fill.size() );

        int skipped = std::count( fill.begin(), fill.end(), 0.0 );

        _matrix.reserve( fill.size() - skipped );

        vector<double>::const_iterator itr = fill.begin();
        for( int i=0; i<numRow; ++i)
        {
            for(int j=0; j<numCol; ++j, ++itr)
            {
                if( *itr != 0.0 )
                {
                    _matrix.push_back( val( i, j, *itr ) );
                }
            }
        }
    }
};