簡體   English   中英

為什么這個struct literal在VS2013中通過地址而不是gcc / clang傳遞時會被破壞?

[英]Why is this struct literal getting corrupted when passed by address in VS2013 but not gcc/clang?

我正在為我維護的庫組裝一個Visual Studio 2013解決方案。 該庫主要使用競技場分配,因此我們有一個分配器接口:

allocator.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的包裝器:

system_allocator.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#include s allocator.h )中聲明為extern ,並作為符號導出(在.def文件中)。 然而,顯然該結構是永遠不會被初始化,因為當我的單元測試嘗試通過system_allocator按地址到其提領操作的功能alloc成員,他們與以“0x000007FEFAD3EB6D(hammer.dll)在錘test.exe的未處理的異常段錯誤:0000005 :訪問沖突讀取位置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)*
    • free 0x00019ffc25ff0001 void(HAllocator_ *,void *)*

特別是因為當我檢查原始struct literal時,一切看起來都很合理:

  • 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 *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

斷點的問題很容易解釋。 Visual C ++調試器通過在函數中放置斷點來工作。 你試圖在函數外面放置一個斷點。 這不受支持。

在機器代碼級別,全局初始化器在main之前在可執行文件中運行,而在DllMain在DLL的情況下運行。 您可能已經注釋掉了MSVC ++的實際初始化程序,因為代碼不是有效的C ++。 是的,我知道問題標記為C,但MSVC ++不支持現代C.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM