C strcpy的怪异行为

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

我用C编写了一个小程序。当我通过
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;