为什么我会出现分段错误?C编程

  • 本文关键字:错误 分段 编程 c fault
  • 更新时间 :
  • 英文 :


这是我的代码,我在那里遇到了seg错误。我很确定这与通过引用有关,但它让我很困惑,我不确定我做得是否正确。

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "utils.h"
#define PI 3.1415926535897932384626433832795
int circleStatistics(double radius, double *diameter, double *circumference, double *area){
  *diameter = radius * 2;
  *circumference = PI * radius * 2;
  *area = PI * radius * radius;
  if (radius <= 0 || diameter == NULL || circumference == NULL || area == NULL)
    printf("An error has occuredn");
    return 1;
  }else{
    return 0;
  }
}

下面是我用来调用函数并测试它的代码

#include "utils.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv){
  // Tests circleStatistics
  double radius = 3;
  double *diameter = NULL, *circumference = NULL, *area = NULL;
  circleStatistics(radius, diameter, circumference, area);
  printf("Expected output: radius = 3, diameter = 6, circumference ~= 18.849555, area ~= 28.2743339n");
  printf("Actual output: radius = %.0f, diameter = %.0f, circumference ~= %.7f, area ~= %.7fn", radius, *diameter, *circumference, *area);
}

您正在取消引用指针参数,然后检查它们是否为NULL。。。试试这样的东西:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "utils.h"
#define PI 3.1415926535897932384626433832795
int circleStatistics(double radius, double *diameter, double *circumference, double *area){
  if (radius <= 0 || diameter == NULL || circumference == NULL || area == NULL)
    printf("An error has occuredn");
    return 1;
  }else{
    /* now I know, that neither of the arguments point to NULL... */
    *diameter = radius * 2;
    *circumference = PI * radius * 2;
    *area = PI * radius * radius;
    return 0;
  }
}

您没有显示调用代码,但很可能您正在为其中一个指针传递NULL。当前代码首先取消引用指针,然后检查它们是否为NULL。你弄错了——你需要在取消引用之前进行检查。

然而,我认为整个设计值得考虑。这是一个传递单个输入值并返回三个输出值的函数。理想情况下,您希望使用函数返回值,但不要使用,因为您需要返回三个不同的值。因此,通过引用来模拟指针。然后你开始担心呼叫者通过NULL的可能性。所有这些都会使代码变得复杂。

您可以简单地忽略用户传递无效参数的可能性,并将需求记录给调用者。这将是一个有效的选择。例如,标准库中的许多函数都是这样做的。一个很好的例子是strlen,它要求您传递一个指向以null结尾的字符串的指针。如果你不满足这个要求会发生什么,没有具体说明。

就我个人而言,我会将这三个输出值封装到一个结构中,从而绕过大多数问题:

struct CircleStats
{
    double diameter;
    double circumference;
    double area;
}
struct CircleStats CalcCircleStats(double radius)
{
    struct CircleStats stats;
    stats.diameter = radius * 2;
    stats.circumference = PI * radius * 2;
    stats.area = PI * radius * radius;
    return stats;
}

这就留下了radius为负的可能性。就我个人而言,我会忽略这种可能性。记录调用方必须提供正半径,并期望它们满足该要求。如果他们不能满足这个要求,那么调用代码中就有问题,期望这个代码能够处理它是不合理的。

最新更新