我在C中编写了一个小程序。当我通过我的Makefile
和clang
编译时,它编译得很完美并且有效。但是,在Xcode中,这个函数表现得不像它应该的那样(或者它表现得很好)喜欢它应该和clang忽略它。)
size_t getUrlForArgAndPlatform(char **dest, const char *arg, const char *platform) {
int isLinux = strcmp(platform, "Linux");
int isOSX = strcmp(platform, "Darwin");
char *platformUrlDelimiter = malloc(6 + 1);
if (isLinux == 0) {
strcpy(platformUrlDelimiter, "linux");
} else if (isOSX == 0) {
strcpy(platformUrlDelimiter, "osx");
} else {
strcpy(platformUrlDelimiter, "common");
}
int length = (int) strlen(kBaseUrl);
length += strlen(platformUrlDelimiter);
length += strlen(arg);
length += 5;
char *buffer = (char *) malloc(length);
if (buffer == NULL) {
exit(EXIT_FAILURE);
}
strcpy(buffer, kBaseUrl);
strcat(buffer, "/");
strcat(buffer, platformUrlDelimiter);
strcat(buffer, "/");
strcat(buffer, arg);
strcat(buffer, ".md");
*dest = malloc(strlen(buffer) + 1);
strcpy(*dest, buffer);
free(platformUrlDelimiter);
free(buffer);
return strlen(buffer) + 1;
}
在10次中有效4次。在其他6次中,Xcode告诉我strcpy(*dest, buffer)
的{{1}}失败了。如果我看一下调试器,我会看到SIGBRT
包含两次相同的字符串。为什么呢?
答案 0 :(得分:2)
您为buffer
计算的尺寸不太正确:
int length = (int) strlen(kBaseUrl);
length += strlen(platformUrlDelimiter);
length += strlen(arg);
length += 5;
最后一部分应该是' + 6'因为"/"
需要空格".md"
,NUL
AND 需要空格{{1}}。
答案 1 :(得分:0)
(已经提到了不正确的长度。)
你的代码中有很多无意义的复制。由于您不修改platformUrlDelimiter
,因此无需复制两次。这更简单:
const char *platformUrlDelimiter = "common";
if (isLinux == 0) {
platformUrlDelimiter = "linux";
} else if (isOSX == 0) {
platformUrlDelimiter = "osx";
}
然后移除对free (platformUrlDelimiter)
的调用。
每次调用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;
现在根本不需要使用buffer
。
此外,代码末尾还有真正的错误:
free(buffer);
return strlen(buffer) + 1;
不得在释放后以任何方式使用buffer
的值。