【问题标题】:Segmentation fault when calling a function returning a pointer调用返回指针的函数时出现分段错误
【发布时间】:2014-07-25 20:26:44
【问题描述】:

在调用 C++ 中返回指针的函数时,我遇到了段错误。这里有什么问题?该函数似乎正在做它应该做的事情,但是当它需要返回时,它就会遇到问题。

#include<iostream>
double * v_scalar_prod(double a, double *b, int n)
{
    double *res ;
    int i;
    for (i = 0; i < n; i++) {
        *(res+i) = a*b[i];
        std::cout << std::setprecision(10) << "res = " << *(res+i) << '\n';
    }
    return res;
}


int main()
{


    double y[3] = {3., 5.45, 2.};
    double *z = new double[3];

    z = v_scalar_prod(4., y, 3);

}

输出:

$ ./program
res = 12
res = 21.8
res = 8
Segmentation fault (core dumped)

【问题讨论】:

  • res 没有任何意义。你应该为它分配一些内存。
  • 你应该使用std::vector(或者类似std::valarray,这里只是va *= 4.;)。
  • 你没有为 res 分配内存。 double* res 只声明了指针变量。事实上,您不仅希望它指向一个有效的double,而且您甚至还需要一个数组(如果它真的是 C++,为什么不按照 cris 建议的那样使用 C++ 方式呢?)。
  • *(res+i) = a*b[i]; 这甚至意味着什么? (value at res + i) = a * (the pointer at b[i])?
  • 我很好奇我得到的反对票。我在这里违反了任何规则吗?我是新来的。这不是此类问题的论坛吗?

标签: c++ function pointers


【解决方案1】:

您为z 分配了内存,但您没有将其传递给函数。此外,您尝试在函数中填充的数组没有为其分配内存。因此,即使没有段错误,您返回的指针也会指向某个随机地址。将其更改为以下内容(这是可能的修复方法之一):

#include<iostream>
double * v_scalar_prod(double a, double *b, int n)
{
    double *res  = new double[3];
    int i;
    for (i = 0; i < n; i++) {
        *(res+i) = a*b[i];
        std::cout  << "res = " << *(res+i) << '\n';
    }
    return res;
}

int main()
{
    double y[3] = {3., 5.45, 2.};
    double *z ;

    z = v_scalar_prod(4., y, 3);
    delete [] z;
}

【讨论】:

  • 做到了。谢谢!!
  • 这可能适用于琐碎的程序,但一旦您需要在任何更复杂的程序中执行此操作或编写一个在多个位置调用 v_scalar_prod 的更大程序,这不是推荐的方法。
  • @PaulMcKenzie 我现在知道了。我再试试 std::vector 或 std:valarray。
  • @Physico - 我发布了一个显示矢量使用情况的答案。
  • @Physico - 您可以使用 C++11 使用初始化语法。 DoubleArray y = {1,2,3};
【解决方案2】:

让我们使用std::vector:

#include <iostream>
#include <vector>
#include <iomanip>
typedef std::vector<double> DoubleArray;

DoubleArray v_scalar_prod(double a, double *b, int n)
{
   DoubleArray res(n);
   for (int i = 0; i < n; i++) 
   {
        res[i] = a*b[i];
        std::cout << std::setprecision(10) << "res = " << res[i] << '\n';
   }
   return res;
}

int main()
{
   double y[3] = {3., 5.45, 2.};
   DoubleArray z = v_scalar_prod(4., y, 3);
}

没有内存泄漏,如果调用 delete[] 则不会跟踪等。此外,此版本可以用于更大、更复杂的程序,而无需担心内存泄漏。

唯一需要审查的是v_scalar_prod 函数中的b 在循环之前和循环期间是否指向有效内存。您还可以将 b 设为 DoubleArray 并通过 const 引用传递它。然后您可以执行以下操作:

DoubleArray v_scalar_prod(double a, const DoubleArray& b)
{
   DoubleArray res(b.size());
   for (int i = 0; i < b.size(); i++) 
   {
        res[i] = a*b[i];
        std::cout << std::setprecision(10) << "res = " << res[i] << '\n';
   }
   return res;
}

现在您不需要n 参数,因为vector 通过调用vector::size() 知道它的大小。

【讨论】:

  • 如果您愿意,可以使用 DoubleArray b 并使用 for (auto &amp;x : b) {x *= a; /*output*/} return b; 或 C++98 等效项。
【解决方案3】:

尝试初始化数组

double* res = new double[n];

或者你想要的任何变化。

这样当你在这里取消引用点时:

*(res+i) = a*b[i];

您可以使用assign运算符将该空间处的值分配给您计算的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多