gcc优化掉复合语句 [英] gcc optimising away compound statement

查看:181
本文介绍了gcc优化掉复合语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在为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 时,编译器可以通过创建对象来评估 get_pointer tmp ,产生它的地址作为statement-expression的值,并销毁对象 tmp 。然后,不存在的对象的now-invalid地址被传递给 smemcpy ,它复制无效数据,因为用于 tmp

当使用 memcpy 时,代码可能工作,因为已被重用于其他用途。 code> memcpy 是GCC已知的特殊函数,GCC以各种特殊方式优化它。



复合文字应该可以工作; 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆