【问题标题】:Decoding what these Valgrind debugger memory errors mean within my code解码这些 Valgrind 调试器内存错误在我的代码中的含义
【发布时间】:2020-01-23 16:34:30
【问题描述】:

这里是 c 的新手。刚刚完成了一个 Linux 子系统的设置,所以我可以运行 Valgrind 进行调试。我正在处理需要多个字符串数组的作业,并有组织地存储这些值。我相信我的代码的逻辑是合理的,但是当它运行时立即退出进程,让我没有时间输入程序将运行的 n 次。我相信这是一个分段错误,并下载了 valgrind 来查明问题。但是,我无法理解这些错误消息的含义。似乎只有一两个错误,但我可能是错的。我可能需要使用动态内存函数(malloc、calloc...)来使其工作,但在内存分配方面我更像是一个初学者,甚至不知道从哪里开始。任何关于我的 valgrind 错误意味着什么,或者我应该如何动态分配内存的建议将不胜感激:)

任何人需要的任何其他信息,请随时询问。

我已经消除了任何我知道可以解决的错误。现在只剩下这两个了。我认为这与分段错误或未正确分配内存有关,但我不确定。

这是我当前的代码。它可能有点混乱,或者有不好的空格。我也对我的编码风格持开放态度:)

    int main() {
int n, i, j = 0, k, m, p, flag, key, count;
char choiceUQ, choiceSS[100];
char nameTemp[100], printStu[n][100];
char stuName[n][100], stuSym[n][n][100];        

scanf("%d", &n); //Scan in n number of times u or q will run

for(i = 0; i < n; i++) { //initialize all symptoms to be null for later if statement.
    for(k = 0; k < n; k++) {
        strcpy (stuSym[k][i], "");
    }
}

for(i = 0; i < n; i++) {
    strcpy(nameTemp, "");
    scanf("%c", &choiceUQ);
    if(choiceUQ == 'u') { 
        flag = 0; //set flag to 0, will be changed if name is already in database.
        scanf("%s", nameTemp);
        for(k = 0; k < i; k++) { //for loop checks if name is already in database.
            if(nameTemp == stuName[k]) { 
                flag = 1; //sets flag if name is in database.
                for(m = 0; m < i; m++) { //checks for next available string array spot for symptoms.
                    if(stuSym[m][k] == "")
                       scanf("%s", stuSym[m][k]);
                }
            }
        }
        if(flag == 0) { //checks for set flag, if no flag is set, it is a new name, so symptom spot will always be 0.
           strcpy(stuName[i], nameTemp);
           scanf("%s", stuSym[0][i]);
        }
}
    if(choiceUQ == 'q') {
        scanf("%s", choiceSS); //checks for input student or symptom, and executes code related to it.
        if(choiceSS == "student") {
            scanf("%s", nameTemp);
            for(k = 0; k < i; k++) { //searches for student name in database
                if(nameTemp == stuName[k]) 
                    key = k;
            }
            for(m = 0; m < i; m++) {
                printf("%s\n", stuSym[m][key]); //prints all symptoms that student has reported
            }
        }
        if(choiceSS == "symptom") {
            count = 0; //initialize count of symptoms at 0
            scanf("%s", nameTemp);
            for(k = 0; k < i; k++) {
                for(m = 0; m < i; m++) {
                   if(nameTemp == stuSym[m][k]) { //nested for loops lead to if loop to check if each student has the given symptom
                      strcpy(printStu[count], stuName[k]);
                      count++;
                    }
                }
            }
            for(p = 0; p < count; p++) { //prints all students copied into printStu array
                printf("%s", printStu[p]);
            }
        }
    }      
}

return 0;

}

我在 valgrind 中遇到的错误如下所示

==4540== error calling PR_SET_PTRACER, vgdb might block

==4540== Use of uninitialised value of size 8
==4540==    at 0x108B9C: main (santos_pandemic2.c:12)


==4540== Use of uninitialised value of size 8
==4540==    at 0x4EB7EC0: __isoc99_scanf (isoc99_scanf.c:27)

^[[A

==4540== Conditional jump or move depends on uninitialised value(s)
==4540==    at 0x108C20: main (santos_pandemic2.c:14)

==4540== Conditional jump or move depends on uninitialised value(s)
==4540==    at 0x109115: main (santos_pandemic2.c:20)

==4540== HEAP SUMMARY:
==4540==     in use at exit: 0 bytes in 0 blocks
==4540==   total heap usage: 1 allocs, 1 frees, 4,096 bytes allocated

==4540== All heap blocks were freed -- no leaks are possible

【问题讨论】:

  • n 尚未初始化时,您希望char stuName[n][100], stuSym[n][n][100]; 做什么?
  • 我只是想如果在设置 n 之前不使用它不会引起问题。只是不确定将最大数组值设置为什么,如果最大值将是用户输入。在 scanf 之后声明它会导致比它修复的问题更多吗?
  • 如果您使用 gcc,请使用 -Wall -Werror 标志进行编译;当您使用未初始化的变量时会出现编译错误,这比尝试调试它们要好得多。始终设置这两个标志进行编译
  • OT: about: scanf("%s", choiceSS); 1) 始终检查返回值(不是参数值)以确保操作成功。注意:scanf() 系列函数返回成功的“输入格式转换说明符”的数量。在这种情况下,除 1 以外的任何值都表示发生了错误。 2) 当使用 '%s' 和/或 '%[...]' 时,总是包含一个比输入缓冲区长度小 1 的 MAX CHARACTERS 修饰符,因为这些说明符总是附加一个 NUL 字节。这也避免了任何可能的缓冲区溢出和随之而来的未定义行为
  • 贴出代码时,请贴出能编译的代码(即使有错误) 贴出的代码缺少#include &lt;stdio.h&gt;#include &lt;string.h&gt;这两条语句

标签: c arrays memory segmentation-fault valgrind


【解决方案1】:
char nameTemp[100], printStu[n][100];
char stuName[n][100], stuSym[n][n][100];

您使用未初始化的值 n 来声明这些数组。 C 不够聪明,无法确定它应该在使用 scanf 给 n 一个值之后声明数组。

由于您希望动态分配这些数组(使用从 scanf 获得的值),我建议使用 malloc 为它们分配内存。或者查看“可变长度数组”以及如何使它们工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 2020-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多