在这个涉及结构和指针的 C 编程问题上遇到分段错误

Posted

技术标签:

【中文标题】在这个涉及结构和指针的 C 编程问题上遇到分段错误【英文标题】:Getting segmentation fault on this C programming problem involving structures and pointers 【发布时间】:2021-08-06 23:52:15 【问题描述】:

我正在研究一个 Hackerrank 问题。我应该使用给定的代码解决问题。

这是给定的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h> 

struct Geometry;

void initRectangle(struct Geometry **object);
void initSquare(struct Geometry **object);
void initCircle(struct Geometry **object);
void initLine(struct Geometry **object);

void printGeometry(struct Geometry* object);

void freeGeometry(struct Geometry* object);

#define SCANF_FMT_CIRCLE    "%f %f %f"
#define SCANF_FMT_RECTANGLE "%f %f %f %f"
#define SCANF_FMT_SQUARE    "%f %f %f"
#define SCANF_FMT_LINE      "%f %f %f %f"


#define PRINTF_FMT_CIRCLE    "Circle with center at %f, %f and radius %f\n"
#define PRINTF_FMT_RECTANGLE "Rectangle with corner at (%f, %f) with width %f and height %f\n"
#define PRINTF_FMT_SQUARE    "Square with corner at (%f, %f) and side %f\n"
#define PRINTF_FMT_LINE      "Line from (%f, %f) to (%f, %f)\n"

int main()

  int n;
  struct Geometry **object;
  scanf("%d", &n);
  printf("%d geometric items\n", n);

  object = malloc(sizeof(struct Geometry*)*n);

  for(int i = 0; i < n; i++)
  
    char objectType[40];
    scanf("%s", objectType);

    if(!strcmp(objectType, "Rectangle"))
    
      initRectangle(&object[i]);
    
    else if (!strcmp(objectType, "Square"))
    
      initSquare(&object[i]);
    
    else if(!strcmp(objectType, "Circle"))
    
      initCircle(&object[i]);
    
    else if(!strcmp(objectType, "Line"))
    
      initLine(&object[i]);
    
    else
    
      printf("Unknown geometric type %s\n", objectType);
      exit(1);
    

  
  
  for(int i = 0; i < n; i++)
  
    printGeometry(object[i]);
  
  
  for(int i = 0; i < n; i++)
  
    freeGeometry(object[i]);
  

  free(object);

示例输入:

6
Line 0.739 0.053 0.380 0.383
Line 0.098 0.158 0.546 0.531
Square 0.120 0.707 0.346
Rectangle 0.769 0.041 0.995 0.859
Rectangle 0.671 0.520 0.246 0.226
Square 0.333 0.721 0.249

样本输出:

6 geometric items
Line from (0.739000, 0.053000) to (0.380000, 0.383000)
Line from (0.098000, 0.158000) to (0.546000, 0.531000)
Square with corner at (0.120000, 0.707000) and side 0.346000
Rectangle with corner at (0.769000, 0.041000) with width 0.995000 and height 0.859000
Rectangle with corner at (0.671000, 0.520000) with width 0.246000 and height 0.226000
Square with corner at (0.333000, 0.721000) and side 0.249000

我需要编写函数。

我尝试了什么:

我写了一个结构体,带有一些布尔变量来指示正在考虑的几何项目:

struct Geometry

    bool isrectangle, isquare, isline, iscircle;
    float x1, x2, y1, y2;
    float square_corner1, square_corner2, side;
    float center1, center2, radius;
    float rectangle_corner1, rectangle_corner2, width, height;
;

接下来,为了初始化结构,我在函数定义中读取这样的输入,使用scanf

void initRectangle(struct Geometry **object)
    scanf(SCANF_FMT_RECTANGLE, &((*object)->rectangle_corner1), &((*object)->rectangle_corner2), &((*object)->width), &((*object)->height));
    (*object)->isrectangle = true;
    (*object)->iscircle = false;
    (*object)->isquare = false;
    (*object)->isline = false;

同理,其他init函数也完成了。其他2个功能是这样完成的:

void printGeometry(struct Geometry* object)
    if (object->iscircle == true)
        printf(PRINTF_FMT_CIRCLE, object->center1, object->center2, object->radius);
    
    else if (object->isline == true)
        printf(PRINTF_FMT_LINE, object->x1, object->x2, object->y1, object->y2);
    
    else if (object->isquare == true)
        printf(PRINTF_FMT_SQUARE, object->square_corner1, object->square_corner2, object->side);
    
    else 
        printf(PRINTF_FMT_RECTANGLE, object->rectangle_corner1, object->rectangle_corner2, object->width, object->height);
    


void freeGeometry(struct Geometry* object)
    free(object);
    object = NULL;
  

我收到这条消息的分段错误:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f3d6afb481f in _IO_vfscanf_internal (s=<optimized out>, 
    format=format@entry=0x402004 "%f %f %f %f", 
    argptr=argptr@entry=0x7fff2d49d5f0, errp=errp@entry=0x0) at vfscanf.c:2445

根据 seg fault 错误消息,我认为我的错误与结构的读取输入有关。为什么会出现分段错误?解决这个问题的正确方法是什么?

【问题讨论】:

看起来传递给函数initfunction的参数无效。请发帖Minimal, Reproducible Example。 Your scanf() line works well. 【参考方案1】:

您应该在object 中分配Geometry * 中的每一个。否则,您传递给initRectangle 的指针本质上是垃圾值,因此取消引用它们会导致分段错误。

【讨论】:

Geometry ** 数组中的每个元素都应该被分配,你可能想要malloc(sizeof(Geometry *) 之类的东西。就目前而言,您只是为整个指针数组分配空间,但每个指针也必须单独分配。这有帮助吗? 是的,它成功了,谢谢。我在 for 循环中做了object[i] = malloc(sizeof(struct Geometry *));

以上是关于在这个涉及结构和指针的 C 编程问题上遇到分段错误的主要内容,如果未能解决你的问题,请参考以下文章

结构中指向数组的 cudaFree 指针上的 CUDA 分段错误

在运行非常旧的C代码时遇到分段错误

使用多个结构的分段错误

C - 指向结构指针的指针 - 分段错误

为啥我在这个 c 代码上遇到分段错误?

[使用结构指针的c ++分段错误