当指向删除和指向不同的对象时,C++ 中的 Seg 错误指针
Posted
技术标签:
【中文标题】当指向删除和指向不同的对象时,C++ 中的 Seg 错误指针【英文标题】:Seg Faulting Pointers in C++ when pointing deleting and pointing to a different object 【发布时间】:2019-12-23 17:11:34 【问题描述】:我开始在 C++ 中使用指针,我觉得我一定错过了 C 和 C++ 之间的一个关键元素。
我在一个类中有一个成员函数,它进行比较然后更改指针指向的内容:
void thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix, matrix* largermatrix, matrix* smallerMatrix)
if(leftSize >= rightSize)
*largermatrix = leftMatrix;
*smallerMatrix = rightMatrix;
else
*largermatrix = rightMatrix;
*smallerMatrix = leftMatrix;
最初我的电话是:
matrix* largerSized = nullptr;
matrix* smallerSized = nullptr;
largerSmallerSetter(LeftMatrix.getNumPieces(), RightMatrix.getNumPieces(), leftMemory, rightMemory, largerSized, smallerSized);
这会产生错误。这是因为 largeSized 和 smallSized 位于地址 0x0。
所以我想我会确保使用初始化指针。
matrix* largerSized = new matrix();
matrix* smallerSized = new matrix();
但是,这个新矩阵完全没用,所以我想摆脱实际的“新矩阵”,我只想让指针指向一个现有的。所以我添加了删除调用来删除对象。当我尝试将指针重新分配给不同的对象时,我得到一个段错误。
现在在 C 中,当我使用 malloc 创建一个指针时,我能够释放该指针。并且指针仍然存在,我可以指向其他地方。
有没有一种方法可以完成我想要的事情,而不会创建一堆只会挂在内存中并导致内存泄漏的对象?
我考虑过使用 std::shared_ptr。但是当我重新分配指针时,我担心当它到达范围的末尾时,它会尝试删除我指向的对象,该对象是在更高的范围内创建的并且需要继续存在。所以我不一定对智能指针感兴趣。
我尝试的另一件事是:
void thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix, matrix* largermatrix, matrix* smallerMatrix)
if(leftSize >= rightSize)
largermatrix = &leftMatrix;
smallerMatrix = &rightMatrix;
else
largermatrix = &rightMatrix;
smallerMatrix = &leftMatrix;
但这一切的作用是,当作用域结束时,传入的指针会恢复到调用函数之前的状态。
【问题讨论】:
【参考方案1】:让我们看看你的代码做了什么。
*largermatrix = leftMatrix;
它取消引用largermatrix
(从而获得指针指向的那块内存)并尝试使用赋值运算符用leftMatrix
的内容填充它(如果您有自定义重载,则可以是自定义操作那个运营商)。因此,如果largermatrix
没有指向任何内容,您将遇到您描述的问题。
另一方面,
largermatrix = &leftMatrix;
这将分配largermatrix
指向leftMatrix
的位置,这就是你想要的。但是,由于largermatrix
是一个局部变量,因此更改不会传播到调用者。因此,largermatrix
应该是对指针的引用。
void thisClass::largerSmallerSetter(int leftSize, int rightSize,
matrix& leftMatrix, matrix& rightMatrix,
matrix*& largermatrix, matrix*& smallerMatrix)
顺便说一句,函数不会更改的其他引用参数是常量引用,如下所示:
void thisClass::largerSmallerSetter(int leftSize, int rightSize,
const matrix& leftMatrix, const matrix& rightMatrix,
matrix*& largermatrix, matrix*& smallerMatrix)
【讨论】:
【参考方案2】:我在一个类中有一个成员函数,它进行比较然后更改指针指向的内容
不,您有一个分配给指针指向的对象的函数。 *
运算符,在这种情况下,dereferences 产生指向对象的指针。如果指针未指向对象,则其行为未定义。
但这一切的作用是,当作用域结束时,传入的指针会恢复到调用函数之前的状态。
不,传递给函数的原始指针从未改变。指针是对象,并且与所有对象一样,默认情况下按值传递。这意味着,例如,largerSized
和 largermatrix
是完全独立的对象。它们唯一的关系是,当您调用函数时,它们最初具有相同的值。更改largermatrix
的值不会修改largerSized
的值。如果你想让你的函数中的赋值修改传递的对象,你需要传递一个引用:
void thisClass::largerSmallerSetter(int leftSize, int rightSize,
matrix& leftMatrix, matrix& rightMatrix,
matrix*& largermatrix, matrix*& smallerMatrix)
// passed by reference --------------------^----------------------^
注意:这也适用于 C。 C 没有引用,但您需要传递一个指向指针的指针,以便在函数内修改调用范围内的指针。
【讨论】:
【参考方案3】:您可以使用多种方法来比较两个矩阵:
更好的选择是返回最小矩阵的地址。例如,
matrix *thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix)
if(leftSize >= rightSize)
return &rightMatrix;
return &leftMatrix;
您可以在C++
中重载比较运算符
bool operator<(const matrix& a, const matrix& b)
return a.getNumPieces() < b.getNumPieces();
您可以在 C++ 中使用指针到指针。
void thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix, matrix** largermatrix, matrix** smallerMatrix)
if(leftSize >= rightSize)
*largermatrix = &leftMatrix;
*smallerMatrix = &rightMatrix;
else
*largermatrix = &rightMatrix;
*smallerMatrix = &leftMatrix;
你可以有引用指针。
void thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix, matrix*& largermatrix, matrix*& smallerMatrix)
if(leftSize >= rightSize)
largermatrix = &leftMatrix;
smallerMatrix = &rightMatrix;
else
largermatrix = &rightMatrix;
smallerMatrix = &leftMatrix;
我对你的问题的评论:
我在一个类中有一个成员函数,它进行比较然后更改指针指向的内容:
要更改任何对象的值,您需要将其作为引用传递或作为指针传递。在您的情况下,您需要更改指针的值,然后您需要传递 pointer as reference
或传递指针的地址。否则,您的函数将更改它自己的本地指针副本。
这会产生错误。这是因为 largeSized 和 smallSized 位于地址 0x0。
这是因为在您的函数中,您试图将一个矩阵复制到指针所指向的矩阵(largermatrix
和smallerMatrix
)。但是,它们不指向任何有效对象。您需要使用new
动态分配对象或传递分配在其他地方的预分配矩阵的地址。
【讨论】:
以上是关于当指向删除和指向不同的对象时,C++ 中的 Seg 错误指针的主要内容,如果未能解决你的问题,请参考以下文章