神奇的分段错误?
magical segmentation fault?
我查看了该站点上的其他类似问题,但我仍然看不出我遗漏了什么。 C 对我来说是一个新的可怕的野兽,所以我确信它很简单,但是当代码到达 while 循环内的 fgets();
行时,我遇到了分段错误(核心转储)。
我尝试将字符串直接写入 currentInput
但仍然得到它,所以我想我以某种方式访问了字符串错误?
我的理解是,分段错误是由访问(程序?)无法访问的内存引起的...
顺便说一句,有没有办法在 strcmp(); 中使用字符串文字?所以我可以比较 "END"?
void runCommands()
{
char * currentInput = (char*)malloc(100); //100 char input buffer
char * cmd = (char*) malloc(CMD_LENGTH);
char * target = (char*) malloc(UID_LENGTH);
char * key = (char*) malloc(KEY_LENGTH);
char * endstr = "END";
cmd = "UNDEF";
target = "UNDEF";
key = "UNDEF";
ushort tokens;
while (strcmp(cmd, endstr) != 0) //Run until command is "END"
{
printf("ENTER INSTRUCTION: ");
fgets(currentInput, sizeof(currentInput), stdin); //FAULT OCCURS HERE
tokens = sscanf(currentInput, "%[^,\n],%[^,\n],%s", cmd, target, key); //parse string for values
if (tokens <= 3 && tokens >= 1) //ensure valid # of tokens passed
{
fprintf(stdout, "TOKENS:\nCMD: %s\ntarget: %s\nkey: %s\n", cmd, target, key);
switch (tokens)
//restore UNDEF for non-existent tokens
{
case 1:
target = "UNDEF";
/* no break */
case 2: //intentional fallthrough
key = "UNDEF";
break;
default:
break;
}
/* handle commands */
if (strcmp(cmd, endstr) == 0)
{
end(keyfile);
} //write file and exit function
else if (strcmp(cmd, "DELETE") == 0)
{
delete(target, key);
} //delete specified key from UID
else if (strcmp(cmd, "VALIDATE") == 0)
{
validate(target, key);
} //valid/not valid based on key presence
else if (strcmp(cmd, "ADD") == 0)
{
add(target, key);
} //add key to target UID
else if (strcmp(cmd, "PRINT") == 0)
{
print(target);
} //print sorted keys for UID or all keys for ALL
else
{
invalidCMD(cmd);
} //error message for invalid command
}
else
{
invalidCMD(currentInput); //use whole input as bad command if invalid format
}
}
free(currentInput);
free(target);
free(key);
free(cmd);
}
您通过覆盖 malloc 返回的指针值导致内存泄漏和未定义的行为:
char * currentInput = (char*)malloc(100); //100 char input buffer
char * cmd = (char*) malloc(CMD_LENGTH);
char * target = (char*) malloc(UID_LENGTH);
char * key = (char*) malloc(KEY_LENGTH);
//...
// This is where you cause the issue
char * endstr = "END";
cmd = "UNDEF";
target = "UNDEF";
key = "UNDEF";
由于您切断了代码,我无法评论您的其余代码以确定还有什么会导致问题。
一件事是您肯定没有正确使用 sizeof()
,因为 sizeof(currentInput)
等于 sizeof(char*)
,而不是字符串的长度。
当您编写 cmd = "UNDEF"
时,您将指针(即 cmd
)设置为字符文字数组的位置。如果你想分配字符串(而不是指向它们的指针),你应该使用 strcpy
。
C 编译器会自动为字符串常量分配 space,但是,它不允许重写它们,您可能正试图在您省略的代码部分中这样做。
您需要阅读一些关于 C 类型和指针的内容。:) 考虑以下更改:
#define CMD_LENGTH 100
#define UID_LENGTH 100
#define KEY_LENGTH 100
void runCommands()
{
char * currentInput = (char*)malloc(100); //100 char input buffer
char * cmd = (char*) malloc(CMD_LENGTH);
char * target = (char*) malloc(UID_LENGTH);
char * key = (char*) malloc(KEY_LENGTH);
char * endstr = (char *)malloc(sizeof(char) * 100);
ushort tokens;
strcpy(cmd, "UNDEF");
strcpy(target, "UNDEF");
strcpy(key, "UNDEF");
while (strcmp(cmd, endstr) != 0) //Run until command is "END"
{
printf("ENTER INSTRUCTION: ");
fgets(currentInput, sizeof(currentInput), stdin);
您不能使用简单的赋值以这种方式将值放入指针中。这样做会有效地用 "END" (例如)转换为十六进制的任何内容覆盖指针,这不是您的进程拥有的内存位置。事实上,如果您收到分段错误,这通常意味着您试图读取不属于您的内存,而访问冲突通常是试图写入不属于您的内存。
我想你的大部分麻烦都是由于无意中覆盖指针造成的。
使用 "magic numbers" 也是非常糟糕的做法...(例如,神奇地分配 100 个字节。你怎么知道它是 100?它总是 100 吗?)你还应该验证 malloc实际上 return 编辑了一个值,而不是假设它确实如此。更典型的调用 Malloc 的方式也已被说明,尽管我没有验证 return。最后,fgets 是超级危险的,因为它是一个无限读取。您更愿意使用允许您指定要读取的最大大小的函数,以避免堆或堆栈上的溢出情况(取决于它是局部变量、全局变量还是指向堆的指针)。
我查看了该站点上的其他类似问题,但我仍然看不出我遗漏了什么。 C 对我来说是一个新的可怕的野兽,所以我确信它很简单,但是当代码到达 while 循环内的 fgets();
行时,我遇到了分段错误(核心转储)。
我尝试将字符串直接写入 currentInput
但仍然得到它,所以我想我以某种方式访问了字符串错误?
我的理解是,分段错误是由访问(程序?)无法访问的内存引起的...
顺便说一句,有没有办法在 strcmp(); 中使用字符串文字?所以我可以比较 "END"?
void runCommands()
{
char * currentInput = (char*)malloc(100); //100 char input buffer
char * cmd = (char*) malloc(CMD_LENGTH);
char * target = (char*) malloc(UID_LENGTH);
char * key = (char*) malloc(KEY_LENGTH);
char * endstr = "END";
cmd = "UNDEF";
target = "UNDEF";
key = "UNDEF";
ushort tokens;
while (strcmp(cmd, endstr) != 0) //Run until command is "END"
{
printf("ENTER INSTRUCTION: ");
fgets(currentInput, sizeof(currentInput), stdin); //FAULT OCCURS HERE
tokens = sscanf(currentInput, "%[^,\n],%[^,\n],%s", cmd, target, key); //parse string for values
if (tokens <= 3 && tokens >= 1) //ensure valid # of tokens passed
{
fprintf(stdout, "TOKENS:\nCMD: %s\ntarget: %s\nkey: %s\n", cmd, target, key);
switch (tokens)
//restore UNDEF for non-existent tokens
{
case 1:
target = "UNDEF";
/* no break */
case 2: //intentional fallthrough
key = "UNDEF";
break;
default:
break;
}
/* handle commands */
if (strcmp(cmd, endstr) == 0)
{
end(keyfile);
} //write file and exit function
else if (strcmp(cmd, "DELETE") == 0)
{
delete(target, key);
} //delete specified key from UID
else if (strcmp(cmd, "VALIDATE") == 0)
{
validate(target, key);
} //valid/not valid based on key presence
else if (strcmp(cmd, "ADD") == 0)
{
add(target, key);
} //add key to target UID
else if (strcmp(cmd, "PRINT") == 0)
{
print(target);
} //print sorted keys for UID or all keys for ALL
else
{
invalidCMD(cmd);
} //error message for invalid command
}
else
{
invalidCMD(currentInput); //use whole input as bad command if invalid format
}
}
free(currentInput);
free(target);
free(key);
free(cmd);
}
您通过覆盖 malloc 返回的指针值导致内存泄漏和未定义的行为:
char * currentInput = (char*)malloc(100); //100 char input buffer
char * cmd = (char*) malloc(CMD_LENGTH);
char * target = (char*) malloc(UID_LENGTH);
char * key = (char*) malloc(KEY_LENGTH);
//...
// This is where you cause the issue
char * endstr = "END";
cmd = "UNDEF";
target = "UNDEF";
key = "UNDEF";
由于您切断了代码,我无法评论您的其余代码以确定还有什么会导致问题。
一件事是您肯定没有正确使用 sizeof()
,因为 sizeof(currentInput)
等于 sizeof(char*)
,而不是字符串的长度。
当您编写 cmd = "UNDEF"
时,您将指针(即 cmd
)设置为字符文字数组的位置。如果你想分配字符串(而不是指向它们的指针),你应该使用 strcpy
。
C 编译器会自动为字符串常量分配 space,但是,它不允许重写它们,您可能正试图在您省略的代码部分中这样做。
您需要阅读一些关于 C 类型和指针的内容。:) 考虑以下更改:
#define CMD_LENGTH 100
#define UID_LENGTH 100
#define KEY_LENGTH 100
void runCommands()
{
char * currentInput = (char*)malloc(100); //100 char input buffer
char * cmd = (char*) malloc(CMD_LENGTH);
char * target = (char*) malloc(UID_LENGTH);
char * key = (char*) malloc(KEY_LENGTH);
char * endstr = (char *)malloc(sizeof(char) * 100);
ushort tokens;
strcpy(cmd, "UNDEF");
strcpy(target, "UNDEF");
strcpy(key, "UNDEF");
while (strcmp(cmd, endstr) != 0) //Run until command is "END"
{
printf("ENTER INSTRUCTION: ");
fgets(currentInput, sizeof(currentInput), stdin);
您不能使用简单的赋值以这种方式将值放入指针中。这样做会有效地用 "END" (例如)转换为十六进制的任何内容覆盖指针,这不是您的进程拥有的内存位置。事实上,如果您收到分段错误,这通常意味着您试图读取不属于您的内存,而访问冲突通常是试图写入不属于您的内存。
我想你的大部分麻烦都是由于无意中覆盖指针造成的。
使用 "magic numbers" 也是非常糟糕的做法...(例如,神奇地分配 100 个字节。你怎么知道它是 100?它总是 100 吗?)你还应该验证 malloc实际上 return 编辑了一个值,而不是假设它确实如此。更典型的调用 Malloc 的方式也已被说明,尽管我没有验证 return。最后,fgets 是超级危险的,因为它是一个无限读取。您更愿意使用允许您指定要读取的最大大小的函数,以避免堆或堆栈上的溢出情况(取决于它是局部变量、全局变量还是指向堆的指针)。