【发布时间】:2020-05-09 14:06:36
【问题描述】:
我有以下代码:
#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 编译器版本我也别无选择 :-(
【问题讨论】:
-
嗯,在 Godbolt 上没有 this 执行错误的最早的 gcc 版本上,我明白了:godbolt.org/z/zJRjEs
-
对齐属性可能只会被堆栈上的对象认可。具有 C++17 新/删除(堆)存储的更新版本的 gcc 应该遵循
alignas关键字。 -
请edit您的问题并添加详细信息,您如何编译、链接和运行您的程序。我刚刚在我的 Ubuntu 系统上使用默认的 g++ 8.3.0 进行了尝试,但无法重现该问题。如stackoverflow.com/questions/37970758/…中所述,我使用了
-fsanitize=address和-lasan -
我用
-fsanitize=address尝试了相同的代码,但没有收到任何错误。但是-fsanitize=undefined也有类似的错误。用细节更新问题 -
@Bodo 命令行已添加。如您所见,我坚持使用 gcc 4.3.2 和 C++98