这个小的C程序为什么会导致分段错误?

3

我正在编写一个小的C程序,练习mallocsscanf库函数。但不幸的是,我遇到了分段错误。我已经谷歌搜索和苦苦挣扎了几个小时,但没有结果。有人能帮我解决这个问题吗?

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

void print_array(int a[], int num_elements);

int main(void) {
    int m;    
    printf("How many numbers do you count: \n");  
    scanf("%d", &m);
    int *a = (int*)malloc(m * sizeof(int*));
    char buf[100];
    setbuf(stdin, NULL);
    if (fgets(buf, sizeof buf, stdin) != NULL) {
        char *p = buf;
        int n, index;
        while (sscanf(p, "%d %n", &a[index], &n) == 1 && index < m) {
            // do something with array[i]
            index++;  // Increment after success @BLUEPIXY
            p += n;
        }
        if (*p != '\0')
            printf("you are giving non-numbers, will be ignored");
    }

    print_array(a, m);
    free(a);
    return 0;
}

void print_array(int a[], int num_elements) {
    int i;
    for (i = 0; i < num_elements; i++) {
        printf("%d ", a[i]);
    }
}

2
你正在为 m 个指针分配一个数组,而不是 m 个整数。代码如下:int* a = (int*)malloc(m*sizeof(int*)); - BoBTFish
1
int n, index; --> int n, index = 0; - BLUEPIXY
sscanf(p, "%d %n", &a[index], &n) == 1 && index < m --> index < m && sscanf(p, "%d %n", &a[index], &n) == 1 - BLUEPIXY
3
开始使用GDB。你的噩梦结束了。 - Pbd
int n,索引; while (sscanf(p,"%d %n",&a[index],&n) == 1 && index < m) 您将某些内容存储在&a[index]中,而索引未初始化。 - hm1912
3个回答

3
你的malloc有问题。用int* a = (int *)malloc(m*sizeof(int)); 替换int* a = (int*)malloc(m*sizeof(int*)); 。 这里你很幸运,因为sizeof intint*小,否则你会遇到很多问题。
我无法重现错误,请下次提供输入文本,并且调试segfault时我依赖gdb。 $ gcc -g prog.c -o prog $ gdb prog
gdb> run [args]
这将在导致segfault的行中断程序。使用此教程了解更多知识。gdb教程

1
您的程序有多个错误:

  • you do not check the return value of scanf(). Invalid input will cause m to remain uninitialized, allocating m * sizeof(int) may fail.

  • The size computed for malloc is incorrect. Casting the return value of malloc() is not necessary in C and considered bad style. Furthermore, you should check for allocation failure. Use this instead:

    int *a = malloc(m * sizeof(int));
    
  • index is uninitialized in sscanf(p, "%d %n", &a[index], &n) definitely causing undefined behavior as you are telling sscanf() to store the int value into some random address in memory.

  • you test index < m after storing to &a[index], causing a potential buffer overflow. Swap the test in front of the sscanf().

这是一个修改后的版本:

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

void print_array(const int a[], int num_elements);

int main(void) {
    int m;    
    printf("How many numbers do you count:\n");  
    if (scanf("%d", &m) != 1 || m <= 0) {
        fprintf(stderr, "invalid input\n");
        return 1;
    }
    int *a = malloc(m * sizeof(int));
    if (a == NULL) {
        fprintf(stderr, "memory allocation failed\n");
        return 1;
    }
    char buf[100];
    setbuf(stdin, NULL);  // why do you want stdin to be unbuffered?
    if (fgets(buf, sizeof buf, stdin) != NULL) {
        char *p = buf;
        int n, index = 0;
        while (index < m && sscanf(p, "%d %n", &a[index], &n) == 1) {
            // do something with array[i]
            index++;  // Increment after success @BLUEPIXY
            p += n;
        }
        if (*p != '\0') {
            printf("you are giving non-numbers or extra input, will be ignored\n");
        }
    }

    print_array(a, m);
    free(a);
    return 0;
}

void print_array(const int a[], int num_elements) {
    for (int i = 0; i < num_elements; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
}

0

大多数错误的[潜在]原因似乎来自于未初始化您的自动变量:

scanf("%d",&m);

如果失败了,那么m的值是未定义的,因为你没有初始化它。
sscanf中,你使用&a[index],但是index没有被初始化,所以它可以被写入任何地方。
另请参阅注释,标识更多错误(例如检查sscanf的返回值)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接