首页 > 解决方案 > 我不明白为什么我的函数只能在结构中交换 2 个值时出现分段错误

问题描述

read_file 功能运行顺利。但是每当我调用重新排序函数时,我都会遇到分段错误。

在这段代码中,我定义了一个包含 2 个坐标(x 和 y)的结构,并使用函数 read_file 在“fleet”数组中保存了一个包含一堆坐标的文件。

输入是这种类型的txt文件 x3 y4 x8 y4 x2 y7 x5 y2 x3 y4 x5 y2 x1 y8 x5 y2 x7 y4 x6 y2 x3 y5 x5 y4 x3 y1 x3 y2 x5 y2 x5 y7

但是我传递给重新排序函数的“舰队”数组只需要前 3 对。在这种情况下。(3 4, 2 7, 3 4)

函数 reorder 应该获取数组并仅评估数组的 2 个元素的 x 坐标,如果第二个大于第一个则交换它们。例如

如果 struct[0].x < struct[1].x 则交换 (struct[0].x, struct[1].x)

然后再和下面的一对

如果 struct[1].x < struct2].x 然后交换 (struct[1].x, struct[2].x)

即使重新排序功能仅由这些行组成,我也会遇到分段错误

void reorder(struct point *fleet)
{

    struct point *temp;
    struct point temp1;
    double c;
    int i;
    if (!(temp = malloc(sizeof(struct point)))){
        free(temp);
        puts("non va");
    }
    c  =  fleet[0].x;
    temp->x = c;

    printf("%lf\n", temp->x);
   
}

我该如何解决这个分段错误?

这是代码

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

struct point {
    double x;
    double y;
};

void Read_file(FILE *f, struct point *fleet, struct  point *hits)
{
    int i, j;
    int dim = 3;
    int dim1 = 5;
    char buf[200];



    if (!(fleet = malloc(dim * sizeof(struct point)))){
        free(fleet);
        puts("doesn't work");
    }
    if (!(hits = malloc(dim1 * sizeof(struct point)))){
        free(fleet);
        puts("doesn't work");
    }
    for (i = 0; i < dim; i++) { 
        fgets(buf, sizeof(buf), f); 
            if(sscanf(buf, "x%lf y%lf", &fleet[i].x, &fleet[i].y) != 2) {puts("non va");}   // control printf 
        printf("%lf %lf\n", fleet[i].x, fleet[i].y);

        
    }
    for (i = 0; i < dim1; i++) {fgets(buf, sizeof(buf), f); 
            if(sscanf(buf, "x%lf y%lf", &hits[i].x, &hits[i].y) != 2) {puts("non va");} // control printf 
        printf("%lf %lf\n", hits[i].x, hits[i].y);
    }
}


void reorder(struct point *fleet)
{

    struct point *temp;
    int i, j;
    if (!(temp = malloc(sizeof(struct point)))){
        free(temp);
        puts("non va");
    }
    for (i = 0; i < 3; i++ ) {
    if ( &fleet[i].x < &fleet[i + 1].x) {
        temp->x = fleet[i].x;
        &fleet[i].x = &fleet[i+1].x;
        &fleet[i+1].x = temp->x;
        }
    }
}



int main(int argc,  char *argv[])
{
    struct point *hits;
    struct point *fleet;
    struct point temp;
    int dim1 =  6;
    FILE *f;
    
    if (argc < 2) {
        puts("e niente, non sono abbaastanza gli aargomenti, mannaggia");
        }
    
    f = fopen(argv[1], "r");

    Leggi_File(f, fleet, hits);
    reorder(fleet);

    
    return 0;
}

标签: arrayscpointersstructswap

解决方案


指针fleet未初始化且具有不确定值

struct point *hits;
struct point *fleet;
//...

所以调用这个函数

reorder(fleet);

导致未定义的行为。

至于功能

void Read_file(FILE *f, struct point *fleet, struct  point *hits);

然后它处理指针的副本fleet

Leggi_File(f, fleet, hits);

因此在函数中更改副本不会影响原始指针。

您必须通过指向指针的指针通过引用传递指针。

例如

void Read_file(FILE *f, struct point **fleet, struct  point **hits);

并称它为

Leggi_File(f, &fleet, &hits);

因此,您应该在函数中编写例如

if (!( *fleet = malloc(dim * sizeof(struct point)))){
    puts("doesn't work");
    return;
}

要访问已分配数组的元素,您可以使用这样的表达式

( *fleet )[i].x

最初初始化指向 NULL 的指针也是一个好主意

struct point *hits = NULL;
struct point *fleet = NULL;

另外例如注意这个循环

for (i = 0; i < 3; i++ ) {
if ( &fleet[i].x < &fleet[i + 1].x) {
    temp->x = fleet[i].x;
    &fleet[i].x = &fleet[i+1].x;
    &fleet[i+1].x = temp->x;
    }
}

由于比较,对于初学者来说没有意义

&fleet[i].x < &fleet[i + 1].x

看来你的意思

fleet[i].x < fleet[i + 1].x

也就是说,您要比较数组的两个元素的数据成员 x。

如果指针指向的分配的动态数组fleet正好有 3 个元素,则循环调用未定义的行为。因为在这种情况下使用表达式

fleet[i + 1].x
      ^^^^^

可能导致访问超出分配数组的内存。


推荐阅读