C++ 如果GCC构建选项带有'-mms位字段',';epoll_event.data.u64';可通过';将值截断为4字节值;epoll#u wait';

C++ 如果GCC构建选项带有'-mms位字段',';epoll_event.data.u64';可通过';将值截断为4字节值;epoll#u wait';,c++,gcc,centos6,epoll,C++,Gcc,Centos6,Epoll,如果GCC构建选项带有-mms位字段,则可通过epoll\u wait将epoll\u event.data.u64值截断为4字节值 我有一个使用epoll的套接字服务器示例,我发现它非常奇怪,当我使用-mms位字段构建时,我无法在epoll\u event.data.u64中获取原始的8字节值。我不知道为什么,我能用某种方式修复它吗 代码如下: ... { epoll_event ev; ev.events = EPOLLIN | EPOLLET;

如果GCC构建选项带有
-mms位字段
,则可通过
epoll\u wait
epoll\u event.data.u64
值截断为4字节值

我有一个使用
epoll
的套接字服务器示例,我发现它非常奇怪,当我使用
-mms位字段构建时,我无法在
epoll\u event.data.u64
中获取原始的8字节值。我不知道为什么,我能用某种方式修复它吗

代码如下:

...
    {
        epoll_event ev;
        ev.events = EPOLLIN | EPOLLET;

        ev.data.u64 = 0x123456789abcdef0;

        printf("epoll_ctl add:size=%ld, ptr=%p, u64=%lu\n", sizeof(ev.data.ptr), ev.data.ptr, ev.data.u64);

        nRetCode = epoll_ctl(nEpollHandle, EPOLL_CTL_ADD, nSocket, &ev);
        printf("epoll_ctl retcode=%d\n", nRetCode);
        SOCKET_JMP_ERROR(nRetCode >= 0);
    }

    // test wait
    {
        int nRetCount = 0;
        int nRemainEventCount = 1;
        epoll_event EpollEvent;
        epoll_event * pEpollEvent = &EpollEvent;

        nRetCount = epoll_wait(nEpollHandle, pEpollEvent, nRemainEventCount, 0);
        printf("epoll_wait nRetCount=%d\n", nRetCount);
        SOCKET_JMP_ERROR(nRetCount >= 0);

        printf("epoll_wait wait:size=%ld, ptr=%p, u64=%lu\n", sizeof((pEpollEvent->data).ptr), (pEpollEvent->data).ptr, (pEpollEvent->data).u64);

    }
...
并且在没有
-mms位字段的情况下构建,输出消息如下:

epoll_ctl add:size=8, ptr=0x123456789abcdef0, u64=1311768467463790320
epoll_ctl retcode=0
epoll_wait nRetCount=1
epoll_wait wait:size=8, ptr=0x123456789abcdef0, u64=1311768467463790320
如果生成选项带有
-mms位字段
,则消息为:

epoll_ctl add:size=8, ptr=0x123456789abcdef0, u64=1311768467463790320
epoll_ctl retcode=0
epoll_wait nRetCount=1
epoll_wait wait:size=8, ptr=0x9abcdef0, u64=2596069104
这是GCC版本,由
GCC-v

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-linux/4.8.5/lto-wrapper
Target: x86_64-linux
Configured with: ../configure -build=x86_64-linux -enable-checking=release -enable-languages=c,c++ -disable-multilib --with-gmp --with-mpfr --with-mpc
Thread model: posix
gcc version 4.8.5 (GCC)
然后,操作系统是
CentOS 6.5

Linux version 2.6.32-431.el6.x86_64 (mockbuild@c6b8.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Nov 22 03:15:09 UTC 2013

有人能解释一下这个问题吗?谢谢你

mms位域
改变了结构的布局方式,在某些情况下可能会导致系统头中定义的结构与系统库ABI不兼容。这很可能是使用
-mms位字段时
epoll
行为不正确的原因

如果编译32位代码,您可以使用
\uuuuu attribute\uuuuu((MS\u struct))
将MS structure布局应用于单个结构,这可能是最好的方法,例如:

#include <stdio.h>

struct a
{
  short a :16;
  int   : 0;
  short b :16;
} __attribute__((ms_struct)) aa;

int main()
{
  printf("sizeof struct a = %d\n", (int)sizeof(struct a));
  printf("sizeof aa = %d\n", (int)sizeof(aa));
  return 0;
}

如果没有
\uuuu属性((ms_struct))
(如果没有
-mms位字段
),它会报告6的大小。

-mms位字段
选项会更改ABI,因此我希望它会破坏所有类型的内容。你能解释一下你为什么使用它,你想达到什么目的吗?也许有更好的办法。除非您了解该选项的作用和含义,否则不应使用该选项。因为我想使用struct位字段,而客户端是由msvc构建的,因此客户端到服务器的通信协议可能需要“-mms位字段”。例如:struct SayHelloToClient{int a:1;int b:1;int c:2;}我相信您可以对单个结构类型使用
ms_struct
属性,而不是使用
-mms位字段编译。这应该可以解决这个问题。我将在下面的回答中详细说明。@ccccycccc您正在编写运行在linux上的代码,您不能使用
-mms位字段
当您构建代码时,它会把很多事情搞砸。您最多可以在希望在linux和msvc代码之间共享的单个结构上放置一个属性,但不能保证msvc和gcc编译器将与整个结构的内存布局ABI兼容-因此您在这方面有点自作主张,如果你想走这条路,你必须自己做实验。好吧,我会尝试一下,谢谢。也许我可以在我的例子中解决它,但实际上这个问题发生在另一个项目中。所以我应该和我的队友讨论。谢谢!谢谢你,朋友,我将尝试使用属性代替。
sizeof struct a = 8
sizeof aa = 8