【发布时间】: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 <stdio.h>和#include <string.h>这两条语句
标签: c arrays memory segmentation-fault valgrind