将打包的struct成员的引用传递给模板。 gcc错误? [英] Passing reference of packed struct member to template. gcc bug?

查看:202
本文介绍了将打包的struct成员的引用传递给模板。 gcc错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个问题,将struct成员传递给了模板函数。该函数的目标是获取成员的地址和大小。这是简单的示例:



这是结构。

  struct TestStruct {
unsigned char elem1;
无符号字符elem2;
uint64_t elem3;
char buf [10000];
int elem4;
无符号字符elem5;
}
__attribute __((打包));

这是模板函数,应获取成员地址

  template< typename T> 
void addData(const T& val)
{
printf(函子内部的地址:%p \n,& val);
}

int main(int argc,char * argv [])
{
TestStruct testdata;
testdata.elem4 = 0;
printf(结构地址为:%p \n,& testdata);
printf( elem4地址为:%p \n,& testdata.elem4);
addData(testdata.elem4);
返回0;
}

问题:属性(打包) );设置(如示例中一样)
模板函数接收到错误的成员地址:



输出:

 结构地址为:0x7fff735bb4e0 
elem4地址为:0x7fff735bdbfa
func内部的地址:0x7fff735bb4dc

如果删除 packed属性,一切正常。
没有错误也没有警告(即使使用-Wall -Wextra也是如此),但是没有将正确的地址传递给该函数。



我读到以下内容:



https:// gcc.gnu.org/bugzilla/show_bug.cgi?id=36566



,发现存在问题,引用了压缩结构成员。
足够有趣,替换const T&与T&在我的模板函数中,产生错误消息:

 错误:无法将压缩字段'testdata.TestStruct :: elem4'绑定到' int&'

所以,我有2个问题:


  1. 为什么不能将打包结构成员的地址作为指针传递,则不能将其作为const引用传递


  2. const T&中会发生什么案件?没有错误,没有警告,但是错误的地址被传递给该函数。众所周知,引用的地址就是变量的地址,引用指向该变量。



解决方案

您发布的链接都回答了您的两个问题。


1。为什么可以将打包结构成员的地址作为指针传递而不能将其作为const引用传递?


Gabriel M. Beddingfield在他的评论


全部分配给obj.s的short&类型和short *是不正确的,并且理想情况下它们都会导致编译器错误。


C ++规范(C ++ 03,第3.9、3.9.1、3.9.2节)非常清除T和 T的指针。有特定于实现的对齐要求。如果您有 T的指针,那么您可以假定它满足对齐要求。我确定C规范使用类似的语言。


我只能在其中添加C ++ 14标准中的相应引号([basic.align ] / 1):


对象类型具有对齐要求(3.9.1,3.9.2),这对地址进行了限制可以分配该类型对象的位置。 alignment 是实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。对象类型对该类型的每个对象都要求对齐要求;可以使用对齐说明符来请求更严格的对齐方式。


其底线是,即使添加一个压缩结构成员也应该是一个错误。 / p>

2。 const T&中会发生什么案件?没有错误,没有警告,但是错误的地址被传递给该函数。众所周知,引用地址就是变量的地址,引用指向该变量。


Jonathan Wakely


常量引用会导致临时创建,您没有绑定到打包字段





最重要的是,这不是错误它本身不能将非const引用绑定到打包的struct字段,所以一个错误是您可以同时获取它的地址。编译器应允许或禁止两者。


I encountered a problem, passing struct member to a template function. The function's goal is to take the address and size of the member. Here is simple example:

This is the struct. It has packed attribute.

struct TestStruct {
    unsigned char       elem1;
    unsigned char       elem2;
    uint64_t            elem3;
    char                buf[10000];
    int                 elem4;
    unsigned char       elem5;
}
__attribute__ ((packed));

this is the template function, which should get a member's address

template<typename T>
void addData(const T &val)
{
        printf ("address inside func: %p \n",&val);
}

int main(int argc, char *argv[])
{
        TestStruct testdata;
        testdata.elem4 = 0;
        printf ("struct address is:   %p \n",&testdata);
        printf ("elem4  address is:   %p \n",&testdata.elem4);
        addData(testdata.elem4);
        return 0;
}

The problem: When attribute ((packed)); is set (like in the example) the template function receives wrong address of the member:

Output:

struct address is:   0x7fff735bb4e0 
elem4  address is:   0x7fff735bdbfa 
address inside func: 0x7fff735bb4dc

If I remove the "packed" attribute, everything is OK. There is no error and no warning (even with -Wall -Wextra), but not the right address is passed to the function.

I read this:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566

and found that there is an issue, getting references to packed-struct members. Interesting enough, replacing const T& with T& in my template function, produces the error message:

error: cannot bind packed field ‘testdata.TestStruct::elem4’ to ‘int&’

So, I have 2 questions:

  1. Why cannot packed-struct members be passed as const references, when their address can be passed as pointer

  2. What happens in the const T& case? There is no error, no warning, but the incorrect address is passed to the function. As we know, the address of reference is the address of the variable, the reference points to.

解决方案

Both of your questions are answered at the link you posted.

1. Why cannot packed-struct members be passed as const references, when their address can be passed as pointer

Gabriel M. Beddingfield wrote in his comment:

All assignments of obj.s to type short& and short* are incorrect, and ideally they would all result in compiler errors.

The C++ spec (C++03, Sects. 3.9, 3.9.1, 3.9.2) are very clear that T and "pointer to T" have implementation-specific alignment requirements. If you have a "pointer to T" then you may assume that it meets the alignment requirements. I'm sure the C spec has similar language.

I can only add to this the corresponding quote from C++14 standard ([basic.align]/1):

Object types have alignment requirements (3.9.1, 3.9.2) which place restrictions on the addresses at which an object of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. An object type imposes an alignment requirement on every object of that type; stricter alignment can be requested using the alignment specifier

The bottom line of it is that even taking an addres of a packed struct member should be an error.

2. What happens in the const T& case? There is no error, no warning, but the incorrect address is passed to the function. As we know, the address of reference is the address of the variable, the reference points to.

Jonathan Wakely wrote:

A const-reference causes a temporary to be created, you didn't bind to the packed field


The bottom line is that it's not a bug itself that you can't bind a non-const reference to a packed struct field, a bug is that at the same time you can take an address of it. The compiler should either allow or disallow both.

这篇关于将打包的struct成员的引用传递给模板。 gcc错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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