gcc优化掉复合语句 [英] gcc optimising away compound statement
问题描述
我在为c中的通用可调整大小的向量实现push_back操作符时遇到了问题。对于通用性,我需要使用void指针作为参数,但实际上我想直接给它赋值。
当我使用<$ c $编译下面的代码时c> gcc -ot test.c -std = c99 ,它会按我的预期打印 10
。
当我向编译选项添加 -O1
(或更高)时,程序打印 0
。
我认为问题出在 smemcpy
代码中,因为当我用 memcpy替换它时
简化代码:
#include< stdio.h>
#include< stdlib.h>
#define get_pointer(value)({__typeof __(value)tmp = value;& tmp;})
//从src复制到dst逐个字节
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));
//通过临时指针将10复制到容器中
smemcpy(container,get_pointer(10),sizeof(int));
$ b printf(%d \ n,((int *)container)[0]);
返回0;
}
在此先感谢您的帮助,
B
定义 get_pointer
表达式中的声明,它是 GCC扩展。它的语义几乎没有记录,并且没有理由相信在声明中声明的对象的存储持续时间 - 表达式会超出声明的评估。
因此,在准备调用 当使用 smemcpy
时,编译器可以通过创建对象来评估
,产生它的地址作为statement-expression的值,并销毁对象 get_pointer
tmp tmp
。然后,不存在的对象的now-invalid地址被传递给 smemcpy
,它复制无效数据,因为用于 tmp
是GCC已知的特殊函数,GCC以各种特殊方式优化它。
memcpy
时,代码可能工作,因为
复合文字应该可以工作; C标准指定函数体内的复合文字具有与封闭块相关的自动存储持续时间。如果我们按如下方式定义 get_pointer
,封闭块将包含整个 smemcpy
调用:
#define get_pointer(value)(&(__typeof __(value)){value})
I am having an issue with implementing a push_back operator for a generic resizable vector in c. For genericity I need to use a void pointer as an argument, but in practice I want to give it values directly.
When I compile the below code with gcc -o t test.c -std=c99
, it prints 10
as I expect.
When I add -O1
(or higher) to the compile options, the program prints 0
.
I think the problem is in the smemcpy
code, as when I replace it with memcpy
I no longer have this problem.
Simplified code:
#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("%d\n", ((int*)container)[0]);
return 0;
}
Thanks in advance for any help,
B
The definition of get_pointer
uses a statement in an expression, which is a GCC extension. The semantics of this are barely documented, and there is no reason to believe the storage duration of an object declared in a statement-expression persists beyond the evaluation of the statement.
Thus, in preparing the call to smemcpy
, the compiler may evaluate get_pointer
by creating the object tmp
, producing its address as the value of the statement-expression, and destroying the object tmp
. Then the now-invalid address of the no-longer-existing object is passed to smemcpy
, which copies invalid data because the space used for tmp
has been reused for another purpose.
The code may work when memcpy
is used because memcpy
is a special function known to GCC, and GCC optimizes it in various special ways.
A compound literal should work; the C standard specifies that a compound literal within the body of a function has automatic storage duration associated with the enclosing block. If we define get_pointer
as follows, the enclosing block includes the entire smemcpy
call:
#define get_pointer(value) (& (__typeof__(value)) { value })
这篇关于gcc优化掉复合语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!