5

Ho una strana situazione. Sto cercando di implementare un dispositivo SDK da 10+ anni per il mio dispositivo di gestione della fotocamera. Il produttore non è più in affari e non ho alcuna possibilità di ottenere un aiuto ufficiale. Quindi eccomi qui, in cerca di aiuto per il mio brutto problema.Comportamento diverso della memoria non allocata tra le versioni di Visual Studio

L'SDK viene fornito con campioni Visual Studio 6.0. Uno dei file include ha una struttura che termina con un array di un byte come sotto;

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

Ma questo singolo byte allocato array di byte riceve fotogrammi video e strano abbastanza, funziona benissimo con Visual Studio versione 6.0. Se provo con Visual Studio 2005/2008/2010, comincio a ricevere i messaggi di errore Memory Access Violation che actully ha senso dal momento che non dovrebbe essere possibile allocare lo spazio a una matrice di dimensioni fisse in seguito, no? Ma lo stesso codice funziona bene con VS 6.0 ?! Probabilmente è causato da differenze di runtime del compilatore o del C++, ma non sono molto esperto su questo argomento, quindi è difficile dire la ragione certa per me.

Ho provato a cambiare la dimensione in un numero massimo previsto di byte come di seguito;

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

Questo lo ha aiutato ottenere lavoro, ma di tanto in tanto ottengo problemi di violazione di accesso di memoria quando si cerca di distruggere l'oggetto decoder della biblioteca.

C'è qualcosa di decisamente sbagliato in questo. Non ho i codici sorgente dell'SDK, solo i file DLL, Lib e Header. Le mie domande sono:

1) È davvero legale allocare spazio a una matrice di dimensioni fisse nella versione di Visual Studio 6.0?

2) Esiste un modo possibile (un'opzione di compilazione, ecc.) Per far funzionare lo stesso codice con le versioni VS/C++ più recenti?

3) Poiché la soluzione alternativa per la modifica del file di intestazione funziona fino a un certo punto ma presenta ancora problemi, conosci un modo migliore per risolvere questo problema?

+0

Immagino che il problema dovrebbe essere altrove. La dimensione dell'array non dovrebbe essere un problema qui, non è intesa ad essere un limite superiore. – BlueWanderer

+2

Si chiama un array flessibile: http://stackoverflow.com/questions/5478706/flexible-array-member-c99-inside-a-structure –

+0

Ma perché otteniamo la violazione di accesso alla memoria allora? Se creo un nuovo oggetto da questa struttura, non sarebbe creato con la dimensione di 1 (+ resto degli elementi della struttura)? Quindi, come possiamo archiviare più di un byte nell'array audioVideoData in seguito? È possibile riallocare la memoria su una matrice di dimensioni fisse? Dal momento che funziona con la versione VS 6.0, potrebbe essere possibile prima, ma per quanto riguarda VS 2005+? –

risposta

3

IIRC è un vecchio trucco per creare una struttura di dimensioni variabili.

considerano

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

il 'nome' ora può essere di lunghezza variabile se l'allocazione appropriata è fatto e sarà sequenzialmente disposte in memoria:

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

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

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

penso che quanto sopra dovrebbe funziona bene anche nelle versioni più recenti di Visual Studio, forse è una questione di impacchettamento, hai fatto #pragma pack (1) per ottenere le strutture sui limiti dei byte? So che VS6 lo aveva come predefinito.

+0

anche la tua risposta non ha risolto il mio problema incluso il trucco del pragma, la tua risposta è corretta e il mio problema sembra irrisolvibile al momento. –

+0

se fossi in te proverei con un buffer molto più grande, un sacco di successo da 10 anni fa, in particolare la velocità. forse c'è qualche altro problema non correlato alla struttura. se aumentando il buffer diminuisce gli errori di accesso alla memoria, potresti invece avere qualche errore di temporizzazione. –

3

Un array di un elemento in una struttura C come questo spesso indica che la dimensione è sconosciuta fino al runtime. (Per un esempio di Windows, vedere BITMAPINFO.)

Di solito, ci saranno altre informazioni (possibilmente nella struttura) che indicano quanto deve essere grande il buffer.Lei non avrebbe mai allocare uno di questi direttamente, ma invece allocare il blocco giusta dimensione della memoria, poi lanciarlo:

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

Il codice presenta quasi certamente un comportamento indefinito, in qualche modo, e non c'è modo per risolvere questo problema, tranne per riparare l'interfaccia o il codice sorgente dell'SDK. Poiché non è più in attività, questo è impossibile.

+0

Tecnicamente, hai ragione - è UB. Realisticamente, la modifica della struttura è stata abbastanza comune abbastanza a lungo che le probabilità di ottenere risultati imprevisti quando la si utilizza "correttamente" sono essenzialmente inesistenti. È improbabile che cambi con la maggior parte dei compilatori da quando C99 e più recente lo benedica come un "membro di array flessibile". –

+0

Non credo che questa risposta abbia un senso nel contesto. "UB" rimuove le restrizioni su come un compilatore arbitrario può gestirle. Ma sappiamo che la libreria è compilata con VC6 e non sarà mai compilata con un altro compilatore, quindi il comportamento è già impostato su pietra. – MSalters

Problemi correlati