C strcpy的怪异行为
我用C编写了一个小程序。当我通过C strcpy的怪异行为,c,xcode,clang,undefined-behavior,buffer-overflow,C,Xcode,Clang,Undefined Behavior,Buffer Overflow,我用C编写了一个小程序。当我通过Makefile和clang编译它时,它可以完美地编译并工作,但是,在Xcode中,这个函数的行为与它应该的不一样(或者它的行为与它应该的一样,而clang忽略了它) 10次中有4次有效。在其他6次中,Xcode告诉我它在strcpy(*dest,buffer)处失败,并发出SIGBRT。如果我看一下调试器,我会发现缓冲区包含两次相同的字符串。为什么?您为缓冲区计算的大小不太正确: int length = (int) strlen(kBaseUrl); leng
Makefile
和clang
编译它时,它可以完美地编译并工作,但是,在Xcode中,这个函数的行为与它应该的不一样(或者它的行为与它应该的一样,而clang忽略了它)
10次中有4次有效。在其他6次中,Xcode告诉我它在
strcpy(*dest,buffer)
处失败,并发出SIGBRT
。如果我看一下调试器,我会发现缓冲区
包含两次相同的字符串。为什么?您为缓冲区计算的大小不太正确:
int length = (int) strlen(kBaseUrl);
length += strlen(platformUrlDelimiter);
length += strlen(arg);
length += 5;
最后一部分应该是“+6”,因为您需要2倍的空间“/”
,用于“.md”
,用于终止NUL
(已经提到了不正确的长度)
你的代码中有很多无意义的复制。由于不修改platformurldimiter
,因此无需复制它两次。这要简单得多:
const char *platformUrlDelimiter = "common";
if (isLinux == 0) {
platformUrlDelimiter = "linux";
} else if (isOSX == 0) {
platformUrlDelimiter = "osx";
}
并删除对free(platformurldimiter)
的调用
每次调用strcat()
(可能)都必须不必要地在缓冲区中循环。我会写:
int length = strlen(kBaseUrl)
+ strlen(platformUrlDelimiter)
+ strlen(arg)
+ 6;
*dest = malloc(length);
if (*dest) {
sprintf (*dest, "%s/%s/%s.md", kBaseUrl, platformUrlDelimiter, arg);
} else {
/* Error */
}
return length;
现在根本不需要使用缓冲区
另外,在代码末尾有一个真正的bug:
free(buffer);
return strlen(buffer) + 1;
在被释放后,您不得以任何方式使用
缓冲区的值。万岁!是的,就是这样。但为什么它不是每次都失败呢?这是由于未定义行为的本质。有时带有这样一个bug的代码在很长一段时间内似乎都能正常工作,直到。。。
free(buffer);
return strlen(buffer) + 1;