构造函数中的分段错误不明确
Unclear segmentation fault in a constructor
我为矩阵对象构建了一个构造函数。数据存储在结构体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在堆上,所有保存在堆中的结构也是如此。所有这些都是使用"new"创建的。我不明白为什么这不起作用。在我将一个新的结构指针推到向量后的一行,我无法读取它(正如我所说的分段错误(。
有什么想法吗?谢谢
编辑:对不起,这是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.
并且-在第一次迭代期间出现分段错误!
这是用于构造*_matrix
:的std::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
指针时,*_matrix
具有fill.size() + 1
元素,而_matrix->front()
仍然是NULL
指针。实际上,您正在取消引用NULL
。
您可能正在寻找reserve()
方法。
编辑:我注意到还有一些其他可以改进的地方:
SparseMatrix
构造函数按值获取fill
。这意味着,为了构建新的SparseMatrix
,需要制作double
对象的向量的完整副本。您应该通过const引用传递fill
- 对于STL容器迭代器,除非需要后增量的结果,否则应该始终使用前增量运算符
- 如果新
val
对象的某个分配引发std::bad_alloc
异常,则会泄漏内存 - 考虑使用池分配器来分配许多
val
对象。一些C/C++运行库实现(例如OpenBSD(会随机化内存分配。在堆上分配许多小对象可能会导致严重的堆碎片化
如果numCol
>fill.size()
,循环将运行到底。
正如其他人所解释的,错误是使用nullptr初始化,而不是保留然后取消引用它们。
您还为所有项目保留了空间,而没有释放未使用的空间。您的稀疏数组将始终使用比传入的原始向量更多的空间。
您不应该为所有这些项目添加新内容。使用值的矢量。这将使您的代码异常安全。
还有一个问题是,你没有检查你是否有权填写。至少应该有一个关于元素数量的断言。
假设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 ) );
}
}
}
}
};
- C++ 编译器错误:P1LinkedList.cpp:145:错误:重载的"to_string(int&)"调用不明确
- gcc出现不明确的模板实例化错误
- "byte":使用Crypto++和Windows SDK时出现不明确的符号错误
- 使用 std::iterator_traits<> 时编译时错误不明确
- 在类Bat代码中,这给了我错误:重载的"Bat()"的调用是不明确的Bat(;)
- 错误错误 C2872:"布尔值":kinect.h 的不明确符号
- C++打印模板容器错误(错误:"运算符<<"的不明确重载)理解?
- 错误:使用复制和交换习惯用法的交换函数中"operator="的重载不明确
- 不明确的错误重载运算符<<QdataStream 子类和个人类
- 模板上下文中的"不明确的基类"错误
- C++ 模板不明确错误
- 为什么调用不明确的 ctor 时没有编译时错误?
- G++ 错误:重载的"abs(无符号 int)"的调用不明确
- 提升错误:"运算符=="的重载不明确
- Qt 中的错误不明确
- C++ 继承错误:不明确的错误
- 超类运算符()错误-不明确
- 符号错误不明确
- 构造函数中的分段错误不明确
- 错误:不明确的默认类型转换(c++)