哪些编译器/链接器选项可能会影响结构在内存中的布局方式

时间:2017-11-11 19:59:29

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

要点: 我想弄清楚我的编译器中的哪些设置会改变stucts在内存中的设置方式

详细信息: 我有两个版本的相同库文件(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结构在内存中的布局方式,从而弄乱了所有指针。< / p>

以下是关联结构

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);
};

2 个答案:

答案 0 :(得分:2)

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

共享对象可能只使用结构的不同定义。根据您发布的定义,您必须使用类似#pragma pack的内容来创建不同的布局,这似乎不太可能是原因。

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

答案 1 :(得分:0)

我弄明白了这个问题。

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

-D_LARGEFILE_SOURCE
-D_LARGEFILE64_SOURCE
-D_FILE_OFFSET_BITS=64