【问题标题】:Segmentation Fault after printing an array?打印数组后出现分段错误?
【发布时间】:2021-02-16 10:23:49
【问题描述】:

我正在编写一个代码来获取用户的输入,并通过数组将其完全打印出来。

void getArrays(char a[10][10], int b[10], int n ){
        printf("Enter number of students and then those students names and scores separated by a space.\n");
        scanf("%d", &n);
        int i = 0;
        while(i < n){
                scanf("%s%d", a[i],&b[i]);
                i++;
        }
}
void printArrays(char a[10][10], int b[10], int n ){
        int j;                                                                                                          
        for(j=0; j<n-1; j++){
               printf("%s %d\n", a[j],b[j] );
        }
}

在这种情况下,a 是一个 10 行乘 10 列的字符数组,而b 是一个整数数组,大小也是 10 行。 n 是用户在创建数组之前输入的数字,指定数组中的字符串数量。 输入看起来像这样:

5
Jimmy 90
Tony 80
Troy 67
Dona 78
Dylan 97

此时它会切断并打印数组,这可以正常工作。但是,在完成名称打印后,终端会吐出大量数字和随机字符串,然后才给我这个错误:

Segmentation Fault (core dumped)

我通过 gbd 调试器运行它,并收到以下消息:

Program received signal SIGSEGV, Segmentation fault.
__strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:65
65      ../sysdeps/x86_64/multiarch/strlen-avx2.S: No such file or directory.

我已经在网站上搜索过这个错误,但已经提出的问题与我的问题无关; Weird Segmentation Fault after printing Segmentation fault core dump 这些只是我见过的两个,它们不是我想要的答案。

我从进一步的搜索中看到,这可能是指针错误,或者是引用数组时代码中的大小差异。我将问题缩小到仅在打印完名称后才发生。所以我尝试将for(j=0; j&lt;n; j++) 更改为for(j=0; j&lt;n-1; j++),它再次给了我同样的问题。

我认为 for 循环可能正在读取我想要的元素数量,即 - 而不是在 3 处停止(如果 n = 3),并且它没有其他要打印的东西,所以它给了我分段错误错误?

在这种情况下,我是否需要使用带有n 的指针,例如&amp;n,还是我的数组大小会出现问题? 调用这些函数的代码如下:

int main(){

        char names[10][15]; // can handle up to 10 students

        int scores[10];

        int num;

        int average;

        getScores(names, scores, num);

        printScores(names, scores, num);
}

【问题讨论】:

  • 显示调用getArrays()printArrays() 的代码。扫描用户输入后,为n 添加打印语句,让我知道你得到了什么值。
  • @meaning-matters 既然你提到它,它会打印出 832。我输入了 3。这很可能是个问题。
  • 你之前不是发过同样的问题吗?
  • @Barmar 我做了,它被关闭了,因为我猜不够清楚,所以我删除了它并更好地解释了我的问题。
  • 你应该编辑它并请求重新打开而不是写一个新问题。

标签: arrays c segmentation-fault gdb


【解决方案1】:

考虑到函数getArrays正在本地修改变量n(因为函数定义是这样的:

void getArrays(char a[10][10], int b[10], int n )

应该是这样的:

void getArrays(char a[10][10], int b[10], int* n )

因此,您提供给printArrays 的 n 值可能未初始化。

另一方面,printArrays 中的循环看起来定义错误:

 for(j=0; j<n-1; j++)

应该是

 for(j=0; j<n; j++)

【讨论】:

    【解决方案2】:

    你需要写:

    int num;
    
    getScores(... &num);
    printScores(... num);
    

    还有:

    getScores(... int* n)
    {
        scanf("%d", n)
        ...
        while (i < *n) {   // Dereference the pointer `n` to get the value again.
    

    使用getScores(... int n),您只需传递num 的当前值,而getScores() 仅修改它的num 的本地副本(即n); num 本身没有改变。

    相反,您必须使用int* n 传递num 的“地址”(或“指向”)。

    您得到的垃圾是因为您根本不更新的main() 中的num 包含一些未定义的值(可能来自处理器堆栈,具体取决于您的平台和 C 编译器的实现) .

    在您的情况下,num 的这个垃圾/未定义值巧合地高于 4。这会导致您扫描的值被打印出来,以及在 names[]scores[] 中进一步上升的大量未定义值。

    在 C 中,通常会在指针前面加上 p,因此您可能想在上面写 pN

    以上是为了让事情正常进行。但还有更多要说的:目前您的数组具有固定大小。如果您为 n 输入 20 和/或输入非常长的名称,您的程序将以未定义的方式运行,因为您的数组太小了。如果你想坚持固定大小的数组,你至少应该检查num的值和输入名称的长度。

    【讨论】:

    • 哦!这实际上很有意义。我想在你回答之前这没有意义。但是,它现在对此有所抱怨,这使问题继续存在。 HW08.c: In function ‘getScores’: HW08.c:8:10: warning: comparison between pointer and integer 8 | while(i &lt; &amp;c){ | ^
    • @NameNotFound 啊,确实忘记了。我在上面添加了一个更正的行。
    • 那就是 100%!谢谢,因为这已经有 2 天的压力了。也简明扼要的解释。我现在很明白了,至少比以前更明白了。如果您不介意我问,如何知道何时使用“*”与“&”等作为指针?
    • @NameNotFound 很高兴它现在可以工作了。我建议您阅读或至少扫描C FAQ 这有点工作,但您会更好地了解事情的运作方式并节省时间。我认为您的 char a[10][10] 函数参数类型仍然存在问题,我让您解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    • 2015-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    相关资源
    最近更新 更多