gcc优化复合语句
我在c中为通用可resize的向量实现push_back运算符时遇到问题。 对于通用性,我需要使用void指针作为参数,但实际上我想直接给它赋值。
当我使用gcc -ot test.c -std=c99
编译下面的代码时,它会按照我的预期打印10
。 当我向编译选项添加-O1
(或更高版本)时,程序将打印0
。
我认为问题在于smemcpy
代码,因为当我用memcpy
替换它时我不再有这个问题。
简化代码:
#include #include #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("%d\n", ((int*)container)[0]); return 0; }
在此先感谢您的帮助,
乙
get_pointer
的定义使用表达式中的语句,该语句是GCC扩展 。 其语义几乎没有记录,并且没有理由相信在statement-expression中声明的对象的存储持续时间会持续超出语句的评估。
因此,在准备对smemcpy
的调用时,编译器可以通过创建对象tmp
来评估get_pointer
,将其地址生成为statement-expression的值,并销毁对象tmp
。 然后将不再存在的对象的现在无效的地址传递给smemcpy
,后者复制无效数据,因为用于tmp
的空间已被重用于其他目的。
当使用memcpy
时,代码可能会起作用,因为memcpy
是GCC已知的特殊函数,GCC以各种特殊方式对其进行优化。
复合字面应该起作用; C标准指定函数体内的复合文字具有与封闭块相关联的自动存储持续时间。 如果我们按如下方式定义get_pointer
,则封闭块包含整个smemcpy
调用:
#define get_pointer(value) (& (__typeof__(value)) { value })
也许问题出在宏观上。 tmp变量是在一个块中定义的,我猜想在重新评估之后,即在输入smemcpy之前,该块立即被保留。 这样,变量的地址变得毫无意义。 一些优化可以覆盖地址,重新利用内存或在未优化的构建中保持原样。 只是一个想法,不能确认。