使用 `malloc` 在函数内定义一个数组并返回该数组给出分段错误

问题描述 投票:0回答:2

我正在尝试从 process.txt 获取输入。所以我做了一个函数来从那个文件中获取这些输入。

process.txt文件的内容:

2
3
4

c
文件:

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

int *takeInput(int *len) {

    FILE *fp = fopen("process.txt", "r");

    fscanf(fp, "%d", len);

    int *arr = malloc(sizeof(int) * (*len));

    for (int i = 0; i < (*len); i++) {
        fscanf(fp, "%d", &arr[i]);
    }

    /* for (int i = 0; i < (*len); i++) { */
    /*     printf("%d\n", arr[i]); */
    /* } */
    /* printf("%p\n", arr); */

    fclose(fp);

    return arr;
}

int main() {

    int *len;
    int *arr = takeInput(len); 

    printf("%d\n", *len);

    return 0;
}

运行这个程序给了我

Segmentation fault (core dumped)
。 我无法在这里检测到错误。

arrays c segmentation-fault malloc
2个回答
0
投票
 fscanf(fp, "%d", len);

尝试访问不属于它的内存。

声明一个指针不会为指向的数据分配内存。使用自动存储持续时间声明的未初始化指针的内容是不确定的,即它可能指向内存中的任何内容,并且进程取消引用它是无效的。

这里不需要动态内存分配。只需声明一个具有自动存储持续时间的

int

int len = 0;

/* Or better as: */
size_t len = 0; /* It can't be negative. */

并将它的地址传递给函数:

int *arr = take_input (&len);

分段错误也可能源于读取

NULL
指针,因为
fopen()
的返回值未经检查就传递给了
fscanf()

如果对

fopen()
的调用返回失败,后续操作将读取/写入
NULL
指针,这将调用未定义的行为。

if (!fopen ("process.txt", "r")) {
    perror ("fopen()");
    complain ();
}

malloc()
也是,返回
NULL
表示失败。应该对其进行类似的检查。


0
投票

关于

len
是使用它的值
len
还是它的地址
&len
存在一些混淆,这导致您将其定义为指针。您应该将
len
定义为类型为
int
的整数。并将其地址传递给
fscanf()
.

这里是修改版:

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

int *takeInput(int *len) {
    FILE *fp = fopen("process.txt", "r");
    if (fp == NULL) {
        fprintf(stderr, "cannot open %s: %s\n",
                "process.txt", strerror(errno));
        return NULL;
    }
    if (fscanf(fp, "%d", len) != 1) {
        fprintf(stderr, "invalid length\n");
        fclose(fp);
        return NULL;
    }

    int *arr = malloc(sizeof(*arr) * (*len));
    if (arr == NULL) {
        fprintf(stderr, "cannot allocate array\n");
        fclose(fp);
        return NULL;
    }

    for (int i = 0; i < (*len); i++) {
        if (fscanf(fp, "%d", &arr[i]) != 1)
            break;
    }
    fclose(fp);
    return arr;
}

int main(void) {
    int len;
    int *arr = takeInput(&len); 
    if (arr != NULL) {
        printf("%d\n", len);
        for (int i = 0; i < len; i++) {
            printf("%d\n", arr[i]);
        }
        free(arr);
    }
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.