clang优化器的一个问题
📜
历史文件已不具备现实意义
今天的一个偶然的发现。FreeBSD clang version 3.6.1 (tags/RELEASE_361/final 237755) 20150525
。clang 3.8 2015/07/20
的版本同样有此问题。
之前, FreeBSD 上 strndup(3) 的实现是这样的:
1
2
3
4
5
6
7
8
9
10
11
12
13
| char *
strndup(const char *str, size_t n)
{
size_t len;
char *copy;
len = strnlen(str, n);
if ((copy = malloc(len + 1)) == NULL)
return (NULL);
memcpy(copy, str, len);
copy[len] = '\0';
return (copy);
}
|
而 OpenBSD 上的实现,则是这样的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| char *
strndup(const char *str, size_t maxlen)
{
char *copy;
size_t len;
len = strnlen(str, maxlen);
copy = malloc(len + 1);
if (copy != NULL) {
(void)memcpy(copy, str, len);
copy[len] = '\0';
}
return copy;
}
|
检查 clang 输出的结果,发现 clang 优化后,FreeBSD 版本会比 OpenBSD 版本多一个 xor %eax, %eax
(amd64),显然是为了 return (NULL)
,从而多出两个字节。而 GCC 则将两份源代码编译成同样的结果(因为在这个 if
块中,已经知道 copy == NULL
,因此并不需要将 %rax
清零)。