【问题标题】:What compiler/linker options could influence how structs are laid out in memory哪些编译器/链接器选项会影响结构在内存中的布局方式
【发布时间】:2017-11-11 19:59:28
【问题描述】:

总结: 我试图弄清楚我的编译器中的哪些设置会改变结构在内存中的设置方式

详情: 我有两个版本的同一个库文件 (libgbm.so),一个作为预构建的二进制文件提供,一个在我自己的机器上编译。一个工作正常,一个引发分段错误。看来我的编译器处理我的数据结构的方式与预编译版本不同。

我提供了一个精简版的代码(参见底部的相关结构)。基本上,它加载一个共享库并调用create_device() 函数。这会返回一个带有一堆函数指针的数据结构 (gbm_device)。

gbm_create_device(int fd)
{
   struct gbm_device *gbm = NULL;
   void *module;
   const struct gbm_backend *backend = NULL

   module = dlopen("/usr/lib/gbm/gbm_pvr.so", RTLD_NOW | RTLD_GLOBAL);
   backend = dlsym(module, "gbm_backend");
   gbm = backend->create_device(fd);

   gbm->surface_create(gbm, width, height, format, flags);
}

这是代码运行方式不同的地方。使用预编译库时,GDB将gbm->surface_create之后的下一步显示为

0xb6beb5d0 in ?? () from /usr/lib/gbm/gbm_pvr.so

当使用我本地编译的版本时,GDB 显示下一步为

0xb6c414a4 in ?? () from /usr/lib/gbm/gbm_pvr.so

我没有 gbm_pvr.so(专有库)的调试符号,但代码显然是进入了两个不同的函数(至少内存地址的最后 3 位应该是相同的)。

我唯一能想到的是,我错过了一些编译器/链接器设置,这些设置改变了 gbm_device 结构在内存中的布局方式,从而弄乱了它获得的所有指针。


这里是关联结构

struct gbm_device {
   /* Hack to make a gbm_device detectable by its first element. */
   struct gbm_device *(*dummy)(int);

   int fd;
   const char *name;
   unsigned int refcount;
   struct stat stat;

   void (*destroy)(struct gbm_device *gbm);
   int (*is_format_supported)(struct gbm_device *gbm,
                              uint32_t format,
                              uint32_t usage);

   struct gbm_bo *(*bo_create)(struct gbm_device *gbm,
                               uint32_t width, uint32_t height,
                               uint32_t format,
                               uint32_t usage);
   struct gbm_bo *(*bo_import)(struct gbm_device *gbm, uint32_t type,
                               void *buffer, uint32_t usage);
   int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data);
   int (*bo_get_fd)(struct gbm_bo *bo);
   void (*bo_destroy)(struct gbm_bo *bo);

   struct gbm_surface *(*surface_create)(struct gbm_device *gbm,
                                         uint32_t width, uint32_t height,
                                         uint32_t format, uint32_t flags);
   struct gbm_bo *(*surface_lock_front_buffer)(struct gbm_surface *surface);
   void (*surface_release_buffer)(struct gbm_surface *surface,
                                  struct gbm_bo *bo);
   int (*surface_has_free_buffers)(struct gbm_surface *surface);
   void (*surface_destroy)(struct gbm_surface *surface);
};

还有

struct gbm_backend {
   const char *backend_name;
   struct gbm_device *(*create_device)(int fd);
};

【问题讨论】:

    标签: pointers gcc memory data-structures compiler-optimization


    【解决方案1】:

    我不认为页面内代码偏移的差异是结构布局差异的证据。由于编译器、汇编器和链接器版本和优化设置的差异,代码布局很容易发生变化。

    共享对象可能只是使用了不同的结构定义。根据您发布的定义,您将不得不使用 #pragma pack 之类的东西来创建不同的布局,这似乎不太可能是原因。

    编辑我错过了struct stat 成员。这确实是一个禁忌,因为它会根据_FILE_OFFSET_BITS 的值(如ino_toff_t)改变大小。可移植代码不应在公共头文件中使用这些类型(和time_t)。

    【讨论】:

      【解决方案2】:

      我发现了问题所在。

      我的构建环境会自动添加以下编译器标志。删除这些解决了问题。

      -D_LARGEFILE_SOURCE
      -D_LARGEFILE64_SOURCE
      -D_FILE_OFFSET_BITS=64 
      

      【讨论】:

        猜你喜欢
        • 2010-12-14
        • 2020-05-09
        • 1970-01-01
        • 1970-01-01
        • 2021-04-21
        • 1970-01-01
        • 1970-01-01
        • 2013-10-06
        • 1970-01-01
        相关资源
        最近更新 更多