结构内部消失后的分段错误(变量corupted)

时间:2016-05-02 23:04:02

标签: c io segmentation-fault strtok strcpy

我的代码有一个非常奇怪的错误,我在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提供的问题是在程序结束时,返回命令之后:

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));

2 个答案:

答案 0 :(得分:2)

你这里遇到各种各样的问题。 第一,行:

strcpy(command_p1, strtok(buffer, " "));

这里有两个问题:

首先,如果buffer包含空字符串,则strtok()将返回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指针,或者可能会变得比你期望的更大。修复所有这些,你的程序可能会工作..如果它没有,你将处于更好的位置,找出真正的错误。

答案 1 :(得分:1)

strcat(t,s)s连接到t end 。因此,为t分配的空间更大,足以容纳t当前持有的字符串以及s。在你的情况下你有

char command_p1[10];
char command_p2[30];

因此

strcat(command_p1, command_p2)

存在缓冲区溢出的风险。错误消息显示实际发生了这种情况。

相关问题