[英]Why is this struct literal getting corrupted when passed by address in VS2013 but not gcc/clang?
I'm putting together a Visual Studio 2013 solution for a library I maintain . 我正在为我维护的库组装一个Visual Studio 2013解决方案。 The library primarily uses arena allocation, so we have an allocator interface: 该库主要使用竞技场分配,因此我们有一个分配器接口:
#define HAMMER_ALLOCATOR__H__
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct HAllocator_ {
void* (*alloc)(struct HAllocator_* allocator, size_t size);
void* (*realloc)(struct HAllocator_* allocator, void* ptr, size_t size);
void (*free)(struct HAllocator_* allocator, void* ptr);
} HAllocator;
[... API functions ... ]
#ifdef __cplusplus
}
#endif
#endif
We also implement a wrapper around malloc
, realloc
and free
: 我们还实现了malloc
, realloc
和free
的包装器:
#include <string.h>
#include <stdlib.h>
#include "internal.h"
void* system_alloc(HAllocator *allocator, size_t size) {
void* ptr = malloc(size + sizeof(size_t));
*(size_t*)ptr = size;
return (uint8_t*)ptr + sizeof(size_t);
}
void* system_realloc(HAllocator *allocator, void* ptr, size_t size) {
if (ptr == NULL)
return system_alloc(allocator, size);
ptr = realloc((uint8_t*)ptr - sizeof(size_t), size + sizeof(size_t));
*(size_t*)ptr = size;
return (uint8_t*)ptr + sizeof(size_t);
}
void system_free(HAllocator *allocator, void* ptr) {
if (ptr != NULL)
free((uint8_t*)ptr - sizeof(size_t));
}
HAllocator system_allocator = {
.alloc = &system_alloc,
.realloc = &system_realloc,
.free = &system_free,
};
The system_allocator
global is declared as extern
in internal.h
(which #include
s allocator.h
), and it is exported as a symbol (in the .def file). system_allocator
全局在internal.h
( #include
s allocator.h
)中声明为extern
,并作为符号导出(在.def文件中)。 However, apparently the struct is never initialized, because when my unit tests try to pass system_allocator
by address to a function that dereferences the alloc
member, they segfault with "Unhandled exception at 0x000007FEFAD3EB6D (hammer.dll) in hammer-test.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF." 然而,显然该结构是永远不会被初始化,因为当我的单元测试尝试通过system_allocator
按地址到其提领操作的功能alloc
成员,他们与以“0x000007FEFAD3EB6D(hammer.dll)在锤test.exe的未处理的异常段错误:0000005 :访问冲突读取位置0xFFFFFFFFFFFFFFFF。“
Inspecting the passed-in pointer in the debugger suggests that something is definitely not right: 检查调试器中的传入指针表明某些东西绝对不对:
Particularly since, when I inspect the original struct literal, everything looks reasonable: 特别是因为当我检查原始struct literal时,一切看起来都很合理:
I tried putting breakpoints on both the declaration and definition of system_allocator
, and VS2013 informs me that "no executable code of the debugger's target code type is associated with this line." 我试图把断点在声明和定义都system_allocator
和VS2013告诉我,“调试器的目标代码类型的无可执行代码与该行相关联。” Does that imply that system_allocator
isn't actually being initialised? 这是否意味着system_allocator
实际上没有被初始化? (If so, then what do those 0x000007fefad31... addresses mean?) (如果是这样,那么那些0x000007fefad31 ...地址是什么意思?)
I've never encountered this problem with gcc or clang, and this is my first time using VS. 我从来没有遇到过gcc或clang这个问题,这是我第一次使用VS. What am I missing? 我错过了什么?
EDIT: per chux's comment, the test which is failing is actually failing in setup. 编辑:每chux的评论,失败的测试实际上是在设置失败。 system_allocator gets passed like this: system_allocator像这样传递:
HBitWriter *w = h_bit_writer_new(&system_allocator);
The line of code that's failing is the first line of HBitWriter *h_bit_writer_new(HAllocator* mm__)
: 失败的代码行是HBitWriter *h_bit_writer_new(HAllocator* mm__)
的第一行HBitWriter *h_bit_writer_new(HAllocator* mm__)
:
HBitWriter *writer = h_new(HBitWriter, 1);
where h_new
is #defined as 其中h_new
是#defined as
#define h_new(type, count) ((type*)(mm__->alloc(mm__, sizeof(type)*(count))))
I bet it is DLL related. 我敢打赌它与DLL有关。 You might have to put together the system_allocater member in the executable instead of passing a structure from the DLL containing the function addresses as the DLL sees them. 您可能必须将system_allocater成员放在可执行文件中,而不是在DLL看到它时从包含函数地址的DLL传递结构。
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683212%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ms683212%28v=vs.85%29.aspx
The problem with breakpoints is fairly easily explained. 断点的问题很容易解释。 The Visual C++ debugger works by putting breakpoints in functions. Visual C ++调试器通过在函数中放置断点来工作。 You're trying to put a breakpoint outside a function. 你试图在函数外面放置一个断点。 That's not supported. 这不受支持。
At machine code level, global initializers are run before main
in an executable, and from DllMain
in case of a DLL. 在机器代码级别,全局初始化器在main
之前在可执行文件中运行,而在DllMain
在DLL的情况下运行。 You've probably commented out the actual initializers for MSVC++, as the code is not valid C++. 您可能已经注释掉了MSVC ++的实际初始化程序,因为代码不是有效的C ++。 Yes, I know the question is tagged C, but MSVC++ doesn't support modern C. 是的,我知道问题标记为C,但MSVC ++不支持现代C.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.