c++ - C指针指向包含对齐的C结构的C++类的对齐问题

标签 c++ c pointers alignment

我有以下代码:

#include <iostream>
#include <stdint.h>
#include <stdio.h>

// Structure from 3rd party that cannot be modified
typedef struct  {
   uint32_t flags;
   uint32_t len;
   uint8_t padding[120];
} mystruct_t __attribute__ ((aligned(128)));

// Classes used internally
class Matcher {
};

class MatcherEQ : public Matcher {
  mystruct_t _bson;
};

Matcher* factory() {
  return new MatcherEQ();
}

// Structure used for C/C++ interface
typedef void* Match_t;

// Pure C API
extern "C" {
void CreateMatch(Match_t *pm) {
  *pm = NULL;
  Matcher *b = factory();
  *pm = (Match_t)b;
}
}

int main(void) {

  // C style code
  puts("C\n");
  Match_t m;

  CreateMatch(&m);

  // C++ code
  std::cout << "C++" << std::endl;
  Matcher *pm = factory();

  return 0;
}


我使用gcc 4.3.2 + Sanitizer在我的工作环境的内部工具链中进行编译。生成的命令行如下所示:
g++ -fsanitize=undefined -fsanitize=address -fno-omit-frame-pointer -fsanitize-recover=address -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wnull-dereference -Wno-unused-local-typedefs -Wno-deprecated -Wformat=2 -D_GLIBCXX_USE_CXX11_ABI=0 -std=c++98 -DDISABLE_MEMORY_ALLOCATORS=1 -march=k8 -pipe -fPIC -fno-strict-aliasing -Wall -Wpointer-arith -Wshadow -Wcast-align -Wimplicit -fno-tree-sra -g -Wno-write-strings -Wno-cast-qual -g3 -O0 -D__UNIX64__ -D__64BIT__ -D__LINUX64__ -D_LP64 -DSLES_10 alignissue.cpp

运行时,我有以下输出:
C

../Sources/Tests/C/alignissue.cpp:48: runtime error: store to misaligned address 0x613000000040 for type 'struct MatcherEQ', which requires 128 byte alignment
0x613000000040: note: pointer points here
 01 00 00 62  be be be be be be be be  be be be be be be be be  be be be be be be be be  be be be be
              ^ 
../Sources/Tests/C/alignissue.cpp:41:7: runtime error: member access within misaligned address 0x613000000040 for type 'struct MatcherEQ', which requires 128 byte alignment
0x613000000040: note: pointer points here
 01 00 00 62  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^ 
../Sources/Tests/C/alignissue.cpp:41:7: runtime error: member access within misaligned address 0x613000000040 for type 'struct MatcherEQ', which requires 128 byte alignment
0x613000000040: note: pointer points here
 01 00 00 62  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  d8 c3 12 a3
              ^ 
C++

=================================================================
==21777==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 384 byte(s) in 1 object(s) allocated from:
    #0 0x7f4aa347500f in operator new(unsigned long) (../../libasan.so+0x10c00f)
    #1 0x403d05 in factory() ../Sources/Tests/C/alignissue.cpp:48
    #2 0x40402e in main ../Sources/Tests/C/alignissue.cpp:75
    #3 0x7f4aa19f5c35 in __libc_start_main (/lib64/libc.so.6+0x1ec35)

Direct leak of 384 byte(s) in 1 object(s) allocated from:
    #0 0x7f4aa347500f in operator new(unsigned long) (../../libasan.so+0x10c00f)
    #1 0x403d05 in factory() ../Sources/Tests/C/alignissue.cpp:48
    #2 0x403e31 in CreateMatch ../Sources/Tests/C/alignissue.cpp:60
    #3 0x403f17 in main ../Sources/Tests/C/alignissue.cpp:71
    #4 0x7f4aa19f5c35 in __libc_start_main (/lib64/libc.so.6+0x1ec35)

SUMMARY: AddressSanitizer: 768 byte(s) leaked in 2 allocation(s).

内存泄漏的原因很明显。

但我想了解并解决对齐地址的问题。

之所以使用typedef void* Match_t,是因为在我的工作环境中,我只能导出纯C API。因此,这是我发现导出对C++类起作用的函数的一种解决方法。

我也没有选择gcc编译器的版本:-(

最佳答案

GCC 4.7.3(具有对godbolt的当前工作执行支持的gcc的最早版本)具有(https://godbolt.org/z/Ndvkkf):

  • alignof(MatcherEQ) = 128
  • alignof(max_align_t) = 16

  • (使用C++ 11 alignof运算符,未指定特定平台)。
    除了“适当对齐”之外,在C++ 2003标准的任何地方,我都找不到与对齐有关的措辞。在C++ 11中(当您发布gcc 4.3.2时还没有完成),我们这样写(强调我的意思):

    [basic.align]/3

    An extended alignment is represented by an alignment greater than alignof(std::max_align_t). It is implementation-defined whether any extended alignments are supported and the contexts in which they are supported (7.6.2). A type having an extended alignment requirement is an over-aligned type. [Note: every over-aligned type is or contains a class type to which extended alignment applies (possibly through a non-static data member).— end note]


    尽管这对于您的情况并不确定(因为C++ 11不适用于gcc 4.3.2),但是可以安全地假设gcc根本不支持过度对齐的类型,至少在动态分配的情况下(请注意,对于stack allocation来说似乎没有问题。

    关于c++ - C指针指向包含对齐的C结构的C++类的对齐问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59876233/

    相关文章:

    c++ - 如何将 bool 类型转换为const char *

    c++ - 简单的 C++11 哈希函数无法编译

    c - 不建议在 fork 时执行外部程序

    c - C 计算字符串中字符数的函数

    c++ - 指针如何变化?

    c - 生成一个 secret 数字并用 C 猜测它

    c++ - 获取系统字体

    c++ - 在 C++ 中使用 `restrict` 类型限定符和 `unique_ptr` 的受限别名

    c - c中的格式说明符值问题

    C 试图将 void 指针转换为另一种类型