C - GCC 优化复合语句



我在为 c 中的通用可调整大小向量实现 push_back 运算符时遇到问题。对于通用性,我需要使用 void 指针作为参数,但实际上我想直接给它值。

当我使用gcc -o t test.c -std=c99编译以下代码时,它会按预期打印10。 当我将-O1(或更高)添加到编译选项时,程序打印0.

我认为问题出在smemcpy代码中,因为当我用memcpy替换它时,我不再有这个问题。

简化代码:

#include <stdio.h>
#include <stdlib.h>
#define get_pointer(value) ({ __typeof__(value) tmp = value; &tmp; })
// copy from src to dst byte by byte
void* smemcpy(void* dst, void const * src, size_t len) {
char * pdst = (char *) dst;
char const * psrc = (char const *) src;
while (len--) {
*pdst++ = *psrc++;
}
return (dst);
}

int main() {
void* container = malloc(sizeof(int));
// copy a 10 into the container via a temporary pointer
smemcpy(container, get_pointer(10), sizeof(int));
printf("%dn", ((int*)container)[0]);
return 0;
}

提前感谢您的任何帮助,

get_pointer的定义在表达式中使用语句,该语句是 GCC 扩展。这方面的语义几乎没有记录,也没有理由相信在语句表达式中声明的对象的存储持续时间会持续到语句的计算之后。

因此,在准备对smemcpy的调用时,编译器可以通过创建对象tmp来计算get_pointer,将其地址生成为语句表达式的值,并销毁对象tmp。然后将不再存在的对象的无效地址传递给smemcpy,这会复制无效数据,因为用于tmp的空间已被重新用于其他目的。

使用memcpy时代码可能会起作用memcpy因为 GCC 已知的特殊函数,GCC 以各种特殊方式对其进行优化。

复合文本应该有效;C 标准指定函数主体中的复合文本具有与封闭块关联的自动存储持续时间。如果我们按如下方式定义get_pointer,则封闭块包括整个smemcpy调用:

#define get_pointer(value) (& (__typeof__(value)) { value })

也许问题出在宏中。 TMP 变量是在块中定义的,我猜该块在其评估后立即保留,即在输入 SMEMMCPY 之前。 这样,变量的地址就变得毫无意义。 地址可能会被一些重新利用内存的优化覆盖,或者在未优化的构建中保持不变。 只是一个想法, 无法确认。

最新更新