c - 为什么这个结构文字在 VS2013 中通过地址而不是 gcc/clang 传递时被破坏?

标签 c struct visual-studio-2013 access-violation

我正在为 a library I maintain 整合一个 Visual Studio 2013 解决方案.该库主要使用竞技场分配,因此我们有一个分配器接口(interface):

分配器.h

#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

我们还围绕 mallocreallocfree 实现了一个包装器:

系统分配器.c

#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,
};

system_allocator 全局在 internal.h 中声明为 extern(#include allocator.h),并将其作为符号导出(在 .def 文件中)。但是,显然该结构从未初始化,因为当我的单元测试尝试通过地址将 system_allocator 传递给取消引用 alloc 成员的函数时,它们会出现段错误“未处理的异常位于0x000007FEFAD3EB6D (hammer.dll) in hammer-test.exe: 0xC0000005: 访问冲突读取位置 0xFFFFFFFFFFFFFFFF。"

在调试器中检查传入的指针表明肯定有什么地方不对:

  • mm__ 0x000000013fb0a094 {hammer-test.exe!HAllocator_ system_allocator} {alloc=0x25ff00019ff625ff realloc=...} HAllocator_ *
    • alloc 0x25ff00019ff625ff void * (HAllocator_ *, unsigned __int64) *
    • realloc 0x9ffa25ff00019ff8 void * (HAllocator_ *, void *, unsigned __int64) *
    • 空闲 0x00019ffc25ff0001 void (HAllocator_ *, void *) *

特别是因为,当我检查原始结构文字时,一切看起来都很合理:

  • system_allocator = {alloc=0x000007fefad31410 {hammer.dll!system_alloc} realloc=0x000007fefad313f7 {hammer.dll!system_realloc} ...}
    • alloc = 0x000007fefad31410 {hammer.dll!system_alloc}
    • realloc = 0x000007fefad313f7 {hammer.dll!system_realloc}
    • free = 0x000007fefad310d2 {hammer.dll!system_free}

我尝试在 system_allocator 的声明和定义上放置断点,VS2013 通知我“没有调试器目标代码类型的可执行代码与此行相关联。”这是否意味着 system_allocator 实际上并未被初始化? (如果是这样,那么那些 0x000007fefad31... 地址是什么意思?)

我从来没有用gcc或clang遇到过这个问题,这是我第一次使用VS。我错过了什么?

编辑:根据 chux 的评论,失败的测试实际上是设置失败。 system_allocator 像这样传递:

HBitWriter *w = h_bit_writer_new(&system_allocator);

失败的代码行是 HBitWriter *h_bit_writer_new(HAllocator* mm__) 的第一行:

HBitWriter *writer = h_new(HBitWriter, 1);

其中 h_new 是#defined as

#define h_new(type, count) ((type*)(mm__->alloc(mm__, sizeof(type)*(count))))

最佳答案

我敢打赌它与 DLL 相关。您可能必须将 system_allocater 成员放在可执行文件中,而不是从 DLL 传递包含 DLL 看到的函数地址的结构。

http://msdn.microsoft.com/en-us/library/windows/desktop/ms683212%28v=vs.85%29.aspx

关于c - 为什么这个结构文字在 VS2013 中通过地址而不是 gcc/clang 传递时被破坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26932750/

相关文章:

SQLite.WP81 扩展 SDK 安装在 VS2013 U2 上但无法引用 WP 8.1 项目中的程序集

tfs - 如何防止 TFS 锁定 App_Data 文件夹中的二进制文件?

c - 为什么 K 的值在此代码中没有增加?

c - 释放内存、函数

c - 为什么不能在 c 中的 main() 之外初始化结构的值?

转换新元素以将它们附加到单链表中

c# - 使用 WPF 控件和 C# 动态生成一个按钮以打开文件对话框并选择一个文件

在C中创建右偏二叉树

c - 为什么cgo的性能这么慢?我的测试代码有问题吗?

go - 两个结构指针之间的类型转换