5

我有一個奇怪的情況。我正在嘗試將一個10多年前的pci攝像頭設備SDK應用於我的相機管理軟件。 Manifacturer不再生意,我沒有機會獲得官方幫助。所以我在這裏,爲我的醜陋問題尋找幫助。Visual Studio版本之間的不同未分配內存行爲

SDK附帶Visual Studio 6.0樣本。其中一個包含文件的結構以下面的一個字節數組結尾;

typedef struct AVData { 
    ... 
    BYTE audioVideoData[1]; 
}AVDATA, *PAVDATA; 

但分配的byte數組這個單字節接收視頻幀和怪異的是,它的工作原理罰款與Visual Studio 6.0版本。如果我使用Visual Studio 2005/2008/2010進行嘗試,我開始得到Memory Access Violation錯誤消息,這些錯誤消息有意義,因爲之後不應該可以將空間分配給固定大小的數組,否則不會?但是,相同的代碼與VS 6.0運行良好?這可能是由於編譯器或C++運行時間差異造成的,但是我對這個主題並不是很有經驗,所以很難告訴我某些原因。

我試着改變大小到預期的最大字節數如下;

typedef struct AVData { 
    ... 
    BYTE audioVideoData[20000]; 
}AVDATA, *PAVDATA; 

這幫助它正常工作,但當我試圖銷燬庫的解碼器對象時,我不時遇到內存訪問衝突問題。

這有一些肯定的錯誤。我沒有SDK的源代碼,只有DLL,Lib和Header文件。我的問題是:

1)在Visual Studio 6.0版本中爲固定大小的數組分配空間真的合法嗎?

2)是否有任何可能的方式(編譯器選項等),以與新版本的VS/C++運行時相同的代碼工作的?

3)由於我的編輯頭文件的變通辦法到一個點,但仍然有問題,你知道什麼更好的辦法讓這個問題的身邊?

+0

我想問題應該在別的地方。數組的大小在這裏不應該是個問題,它並不是一個上限。 – BlueWanderer

+2

它被稱爲一個靈活的數組:http://stackoverflow.com/questions/5478706/flexible-array-member-c99-inside-a-structure –

+0

但是,爲什麼我們會得到內存訪問衝突呢?如果我從這個結構創建一個新的對象,是不是創建的大小爲1(+其餘的結構元素)?那麼,我們以後如何將多個字節存儲到audioVideoData數組呢?是否有可能重新分配內存到一個固定大小的數組?由於它適用於VS 6.0版本,因此可能更早些,但VS 2005+怎麼樣? –

回答

3

IIRC它的一個古老的技巧,以創建一個大小可變的結構。

考慮

struct { 
    int len; 
    char name[1]; 
} s; 

「名字」,現在可以變長的,如果適當的分配完成,它會在內存中依次佈置:

char* foo = "abc"; 
int len = strlen(foo); 

struct s* p = malloc(sizeof(int) + len + 1); 

p->len = len; 
strcpy(p->name, foo); 

我覺得上面應該在新版本的Visual Studio中也可以正常工作,也許這是一個打包問題,你做了#pragma pack(1)來獲得字節邊界上的結構嗎?我知道VS6有默認的。

+0

即使你的回答沒有解決我的問題,包括雜注技巧,你的答案是正確的,我的問題似乎目前無法解決。 –

+0

如果我是你,我會嘗試一個更大的緩衝區,很多發生在10年前,特別是速度。也許還有一些與結構無關的其他問題。如果增加緩衝區會降低內存訪問錯誤,您可能會遇到某些時間錯誤。 –

3

像這樣的C結構中的單元素數組通常意味着直到運行時才知道大小。 (對於Windows示例,請參閱BITMAPINFO。)

通常,會有一些其他信息(可能在結構中)告訴您緩衝區需要多大。你絕不會分配這些直接的一個,而是分配的內存大小合適的塊,然後將它轉換:

int size = /* calculate frame size somehow */ 
AVDATA * data = (AVDATA*) malloc(sizeof(AVDATA) + size); 
// use data->audioVideoData 
1

的代碼幾乎可以肯定表現在某種程度上不確定的行爲,有沒有辦法解決這個問題,除了修復SDK的界面或源代碼。由於它已不再生意,這是不可能的。

+0

從技術上講,你是對的 - 這是UB。實際上,struct hack已經足夠普及了足夠長的時間,以至於在「正確」使用它時獲得意外結果的機會基本上不存在。這是不可能改變大多數編譯器,因爲C99和更新的祝福這是一個「靈活的陣列成員」。 –

+0

我不認爲這個答案在上下文中是有意義的。 「UB」取消了對任意編譯器如何處理它的限制。但是我們知道該庫是用VC6編譯的,並且永遠不會與另一個編譯器一起編譯,因此這種行爲已經成爲現實。 – MSalters

相關問題