【问题标题】:Seg Faulting Pointers in C++ when pointing deleting and pointing to a different object当指向删除和指向不同的对象时,C++ 中的 Seg 错误指针
【发布时间】: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;
    }
}

但这一切的作用是,当作用域结束时,传入的指针会恢复到调用函数之前的状态。

【问题讨论】:

    标签: c++ pointers segmentation-fault


    【解决方案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 产生指向对象的指针。如果指针未指向对象,则其行为未定义。

      但这一切的作用是,当作用域结束时,传入的指针会恢复到调用函数之前的状态。

      不,传递给函数的原始指针从未改变。指针是对象,并且与所有对象一样,默认情况下按值传递。这意味着,例如,largerSizedlargermatrix 是完全独立的对象。它们唯一的关系是,当您调用函数时,它们最初具有相同的值。更改largermatrix 的值不会修改largerSized 的值。如果你想让你的函数中的赋值修改传递的对象,你需要传递一个引用:

      void thisClass::largerSmallerSetter(int leftSize, int rightSize,
                                          matrix& leftMatrix, matrix& rightMatrix,
                                          matrix*& largermatrix, matrix*& smallerMatrix)
      // passed by reference --------------------^----------------------^
      

      注意:这也适用于 C。 C 没有引用,但您需要传递一个指向指针的指针,以便在函数内修改调用范围内的指针。

      【讨论】:

        【解决方案3】:

        您可以使用多种方法来比较两个矩阵:

        1. 更好的选择是返回最小矩阵的地址。例如,

          matrix *thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix)
          {
              if(leftSize >= rightSize)
                  return &rightMatrix;
              return &leftMatrix;
          }
          
        2. 您可以在C++ 中重载比较运算符

          bool operator<(const matrix& a, const matrix& b)
          {
              return a.getNumPieces() < b.getNumPieces();
          }
          
        3. 您可以在 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;
              }
          }
          
        4. 你可以有引用指针。

          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。

        这是因为在您的函数中,您试图将一个矩阵复制到指针所指向的矩阵(largermatrixsmallerMatrix)。但是,它们不指向任何有效对象。您需要使用new 动态分配对象或传递分配在其他地方的预分配矩阵的地址。

        【讨论】:

          猜你喜欢
          • 2011-05-02
          • 1970-01-01
          • 1970-01-01
          • 2013-04-14
          • 2013-09-09
          • 2010-09-08
          • 2020-06-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多