2011-09-10 13 views
2

我已经为矩阵对象构建了一个构造函数。数据存储在struct val的数组中,该数组又保存位置(在矩阵中)和值。这是代码:构造函数中的不清楚的段错误

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

你会发现,我已经添加COUT只是验证的push_back并没有真正为我工作。 _matrix堆积如山,其中所有结构也在堆叠中。所有使用'新'创建。我不明白为什么这不起作用。在我将一个新的结构指针推向向量之后,我无法读取它(分段错误,如我所说)。

任何想法?谢谢!

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

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

而且 - 在第一次迭代过程中发生分段错误!

+1

什么GDB告诉你吗? Valgrind的?你为什么要存储指针? –

回答

4

这是正在用于构建*_matrixstd::vector<val *>构造:

explicit vector (size_type n, const val *& value = val *(), const std::allocator<val *>& = std::allocator<val *>()); 

n组构造函数的调用,以fill.size()产生具有fill.size()默认构造val *对象(所有NULL)的新std::vector<val *>。当你推回一个新的val指针时,*_matrixfill.size() + 1元素,并且_matrix->front()仍然是一个NULL指针。实际上,您正在取消引用NULL

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

编辑:有,我注意到一些其他的东西可以改善:

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

如果numCol>fill.size(),您的循环将结束运行。

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