在这个微小的c程序中导致分段错误错误的原因是什么?

时间:2017-02-11 10:47:58

标签: c

我正在编写一个小型c程序来练习mallocsscanf库函数。但不幸的是我得到了分段错误错误。我用Google搜索并挣扎了好几个小时但没有结果。任何人都可以引导我走出这个?

#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]);
    }
}

3 个答案:

答案 0 :(得分:3)

您的malloc有问题。将int* a = (int*)malloc(m*sizeof(int*));替换为int* a = (int *)malloc(m*sizeof(int));。 你很幸运,sizeof int小于int*,否则你可能会遇到很多问题。

我无法重现错误,下次更好地提供输入文本,但调试segfault我依赖于gdb。

$ gcc -g prog.c -o prog

$ gdb prog

GDB&GT;运行[args]

这会破坏导致段错误的程序。使用本教程可获得更多知识。 gdb tutorial

答案 1 :(得分:1)

您的程序有多处错误:

  • 您不检查scanf()的返回值。输入无效会导致m保持未初始化状态,分配m * sizeof(int)可能会失败。

  • malloc计算的大小不正确。在C中不需要转换malloc()的返回值,并将其视为错误的样式。此外,您应该检查分配失败。请改用:

    int *a = malloc(m * sizeof(int));
    
  • indexsscanf(p, "%d %n", &a[index], &n)中未初始化,肯定会导致未定义的行为,因为您告诉sscanf()int值存储到内存中的某个随机地址中。

  • 您在存储到index < m后测试&a[index] ,导致潜在的缓冲区溢出。在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");
}

答案 2 :(得分:0)

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

scanf("%d",&m);

如果失败,那么m有一个未定义的值,因为你没有初始化它。

sscanf中的{p>您使用&a[index],但index尚未初始化,因此可以在任何地方写入。

另请参阅注释,以识别更多错误(例如,检查sscanf的返回值)。