结构内部消失后的分段错误(变量已损坏)
Segmentation fault after the inner of the struct disappear (variable corupted)
我的代码有一个非常奇怪的错误,我在 VS 2015 和 eclipse 中 运行:
int main(int argc, const char**argv) {
FILE *input = stdin;
FILE *output = stdout;
if(!argumentsValid(argv, argc)){
mtmPrintErrorMessage(stderr, MTM_INVALID_COMMAND_LINE_PARAMETERS);
return 1;
}
if(!changeIO(&input, &output, argv, argc)){
mtmPrintErrorMessage(stderr, MTM_CANNOT_OPEN_FILE);
return 1;
}
char buffer[MAX_LEN + 1];
Yad3Service yad3Service = yad3ServiceCreate();
if(!yad3Service){
mtmPrintErrorMessage(stderr, MTM_OUT_OF_MEMORY);
deallocateAndClose(input, output, &yad3Service);
}
int j = 0;
while (fgets(buffer, MAX_LEN, input) != NULL) {
j++;
printf("%d\n", j);
char command_p1[10];
strcpy(command_p1, strtok(buffer, " "));
if (!strcmp(command_p1, "\n") || command_p1[0] == '#') continue;
char command_p2[30];
strcpy(command_p2 + 1, strtok(NULL, " "));
command_p2[0] = ' ';
char command[40];
strcpy(command, strcat(command_p1, command_p2));
char* command_arguments[10];
int i = 0;
while((command_arguments[i++] = strtok(NULL, " ")));
Yad3ServiceResult res = command_parser(&yad3Service, command,
command_arguments, output);
if(res != YAD3_SUCCESS){
if(res == YAD3_OUT_OF_MEMORY){
deallocateAndClose(input, output, &yad3Service);
mtmPrintErrorMessage(stderr, ((MtmErrorCode)((int)res)));
return 1;
}
mtmPrintErrorMessage(stderr, ((MtmErrorCode)((int)res)));
}
}
deallocateAndClose(input, output, &yad3Service);
return 0;
}
visual studio给出的问题是在程序的末尾,在return命令之后:
Run-Time Check Failure #2 - Stack around the variable 'command_p1' was corrupted.
并且 eclipse 正在做一些更奇怪的事情,同时在第 34 次迭代时,Yad3Service 的内部字段(这是一个其中分配了内存的结构)被清除并且内部地址似乎不存在(在调试),它们就消失了,下次我访问结构指针的内部字段时,我得到了分段错误。
可能是关于内存在 strcpy 或 strtok 期间以某种方式损坏,我不明白发生了什么。有人 ???
做完这条线后奇怪的消失了:
strcpy(command, strcat(command_p1, command_p2));
你这里有各种各样的问题。
第一行:
strcpy(command_p1, strtok(buffer, " "));
这里有两个问题:
首先,如果 buffer
包含空字符串,strtok() 将 return NULL,这对您的 strcpy() 无效。
其次,您的 command_p1
被声明为一个 char[10] 数组。您绝对确定缓冲区中的第一个标记永远不会超过 9 个字符(不包括空终止符)吗?这应该总是提前检查,或者使用 strlcpy()
(http://linux.die.net/man/3/strlcpy) 如果它在您的系统上可用。当您不确定要复制的内容的大小时,切勿使用 strcpy()
。如果你没有 strlcpy,你可以使用下面的常用习惯用法:
char mybuffer[100];
/* copy as much of mysource into mybuffer as will fit. */
/* the result may NOT be null terminated */
strncpy(mybuffer, mysource, sizeof(mybuffer));
/* make sure the string is null terminated */
mybuffer[sizeof(mybuffer)-1] = 0;
同样的注意事项适用于程序中的所有字符串处理。在几个地方,您要对字符串的长度做出假设,而在用 C 编程时,您永远不应该这样做。
逐行检查您的程序,思考您复制到任何字符串缓冲区中的内容可能会变成 NULL 指针或可能比您预期的更大的每种可能情况。修复所有这些问题,您的程序可能会正常工作。如果它不正常,您将能够更好地找出真正的问题所在。
strcat(t,s)
将 s
连接到 t
的 end 上。因此,分配给 t
的 space 最好足够大以容纳 t
当前拥有的字符串以及 s
。在你的情况下你有
char command_p1[10];
char command_p2[30];
因此
strcat(command_p1, command_p2)
有缓冲区溢出的风险。错误消息表明这确实发生了。
我的代码有一个非常奇怪的错误,我在 VS 2015 和 eclipse 中 运行:
int main(int argc, const char**argv) {
FILE *input = stdin;
FILE *output = stdout;
if(!argumentsValid(argv, argc)){
mtmPrintErrorMessage(stderr, MTM_INVALID_COMMAND_LINE_PARAMETERS);
return 1;
}
if(!changeIO(&input, &output, argv, argc)){
mtmPrintErrorMessage(stderr, MTM_CANNOT_OPEN_FILE);
return 1;
}
char buffer[MAX_LEN + 1];
Yad3Service yad3Service = yad3ServiceCreate();
if(!yad3Service){
mtmPrintErrorMessage(stderr, MTM_OUT_OF_MEMORY);
deallocateAndClose(input, output, &yad3Service);
}
int j = 0;
while (fgets(buffer, MAX_LEN, input) != NULL) {
j++;
printf("%d\n", j);
char command_p1[10];
strcpy(command_p1, strtok(buffer, " "));
if (!strcmp(command_p1, "\n") || command_p1[0] == '#') continue;
char command_p2[30];
strcpy(command_p2 + 1, strtok(NULL, " "));
command_p2[0] = ' ';
char command[40];
strcpy(command, strcat(command_p1, command_p2));
char* command_arguments[10];
int i = 0;
while((command_arguments[i++] = strtok(NULL, " ")));
Yad3ServiceResult res = command_parser(&yad3Service, command,
command_arguments, output);
if(res != YAD3_SUCCESS){
if(res == YAD3_OUT_OF_MEMORY){
deallocateAndClose(input, output, &yad3Service);
mtmPrintErrorMessage(stderr, ((MtmErrorCode)((int)res)));
return 1;
}
mtmPrintErrorMessage(stderr, ((MtmErrorCode)((int)res)));
}
}
deallocateAndClose(input, output, &yad3Service);
return 0;
}
visual studio给出的问题是在程序的末尾,在return命令之后:
Run-Time Check Failure #2 - Stack around the variable 'command_p1' was corrupted.
并且 eclipse 正在做一些更奇怪的事情,同时在第 34 次迭代时,Yad3Service 的内部字段(这是一个其中分配了内存的结构)被清除并且内部地址似乎不存在(在调试),它们就消失了,下次我访问结构指针的内部字段时,我得到了分段错误。
可能是关于内存在 strcpy 或 strtok 期间以某种方式损坏,我不明白发生了什么。有人 ???
做完这条线后奇怪的消失了:
strcpy(command, strcat(command_p1, command_p2));
你这里有各种各样的问题。 第一行:
strcpy(command_p1, strtok(buffer, " "));
这里有两个问题:
首先,如果 buffer
包含空字符串,strtok() 将 return NULL,这对您的 strcpy() 无效。
其次,您的 command_p1
被声明为一个 char[10] 数组。您绝对确定缓冲区中的第一个标记永远不会超过 9 个字符(不包括空终止符)吗?这应该总是提前检查,或者使用 strlcpy()
(http://linux.die.net/man/3/strlcpy) 如果它在您的系统上可用。当您不确定要复制的内容的大小时,切勿使用 strcpy()
。如果你没有 strlcpy,你可以使用下面的常用习惯用法:
char mybuffer[100];
/* copy as much of mysource into mybuffer as will fit. */
/* the result may NOT be null terminated */
strncpy(mybuffer, mysource, sizeof(mybuffer));
/* make sure the string is null terminated */
mybuffer[sizeof(mybuffer)-1] = 0;
同样的注意事项适用于程序中的所有字符串处理。在几个地方,您要对字符串的长度做出假设,而在用 C 编程时,您永远不应该这样做。
逐行检查您的程序,思考您复制到任何字符串缓冲区中的内容可能会变成 NULL 指针或可能比您预期的更大的每种可能情况。修复所有这些问题,您的程序可能会正常工作。如果它不正常,您将能够更好地找出真正的问题所在。
strcat(t,s)
将 s
连接到 t
的 end 上。因此,分配给 t
的 space 最好足够大以容纳 t
当前拥有的字符串以及 s
。在你的情况下你有
char command_p1[10];
char command_p2[30];
因此
strcat(command_p1, command_p2)
有缓冲区溢出的风险。错误消息表明这确实发生了。