5

estoy teniendo una situación extraña. Estoy tratando de implementar un SDK de dispositivo de cámara pci de más de 10 años en mi software de administración de la cámara. Manifacturer ya no está en el negocio y no tengo ninguna posibilidad de obtener ayuda oficial. Así que aquí estoy, buscando alguna ayuda para mi feo problema.Diferente comportamiento de memoria sin asignar entre versiones de Visual Studio

SDK viene con Visual Studio 6.0 muestras. Uno de los archivos de inclusión tiene una estructura que termina con una matriz de un byte como a continuación;

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

Pero este único octeto asignado matriz de bytes recibe tramas de vídeo y bastante raro, que funciona bien con la versión de Visual Studio 6.0. Si lo intento con Visual Studio 2005/2008/2010, empiezo a recibir mensajes de error Memory Access Violation, lo que realmente tiene sentido ya que después no se puede asignar espacio a una matriz de tamaño fijo, ¿no? Pero el mismo código funciona bien con VS 6.0 ?! Probablemente sea causado por el compilador o las diferencias de tiempo de ejecución de C++, pero no tengo mucha experiencia en este tema, por lo que es difícil decir la razón cierta para mí.

Intenté cambiar el tamaño a un número máximo de bytes esperado como el siguiente;

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

Esto le ayudó a conseguir trabajo, pero de vez en cuando me sale de memoria problemas de infracción de acceso cuando se trata de destruir el objeto decodificador de la biblioteca.

Hay algo definitivamente malo en esto. No tengo los códigos fuente del SDK, solo los archivos DLL, Lib y Header. Mis preguntas son:

1) ¿Es realmente legal asignar espacio a una matriz de tamaño fijo en la versión de Visual Studio 6.0?

2) ¿Hay alguna manera posible (una opción del compilador, etc.) de hacer que el mismo código funcione con versiones VS más recientes/tiempos de ejecución C++?

3) Debido a que mi forma de editar el archivo de encabezado funciona hasta cierto punto pero aún tengo problemas, ¿conoce alguna forma mejor de solucionar este problema?

+0

supongo que el problema debe estar en otro lugar. El tamaño de la matriz no debería ser un problema aquí, no es la intención de ser un límite superior. – BlueWanderer

+2

Se llama una matriz flexibles: http://stackoverflow.com/questions/5478706/flexible-array-member-c99-inside-a-structure –

+0

Pero, ¿por qué obtenemos la Violación de acceso de memoria, entonces? Si creo un nuevo objeto a partir de esta estructura, ¿no se crearía con el tamaño de 1 (+ resto de los elementos de la estructura)? Entonces, ¿cómo podemos almacenar más de un byte a la matriz audioVideoData después? ¿Es posible reasignar memoria a una matriz de tamaño fijo? Dado que funciona con la versión VS 6.0, podría ser posible antes, pero ¿qué pasa con VS 2005+? –

Respuesta

3

IIRC es un viejo truco para crear una estructura que es de tamaño variable.

consideran

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

el 'nombre' ahora puede ser de longitud variable si la asignación apropiada está hecho y se colocarán de forma secuencial en la memoria:

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

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

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

Creo que lo anterior debe funciona bien en las versiones más nuevas de Visual Studio también, tal vez es una cuestión de empaquetamiento, ¿has hecho #pragma pack (1) para obtener estructuras en los límites de bytes? Sé que VS6 tenía eso por defecto.

+0

aunque su respuesta no resolvió mi problema, incluyendo el truco pragma, su respuesta es correcta y mi problema parece imposible de resolver por el momento. –

+0

si yo fuera tú lo intentaría con un búfer mucho más grande, sucedieron muchas cosas desde hace 10 años, especialmente la velocidad. tal vez haya algún otro problema no relacionado con la estructura. si al aumentar el buffer se reducen los errores de acceso a la memoria, es posible que tenga un error de tiempo. –

3

Una matriz de un elemento en una estructura C como esta a menudo significa que el tamaño es desconocido hasta el tiempo de ejecución. (Para ver un ejemplo de Windows, consulte BITMAPINFO.)

Normalmente, habrá otra información (posiblemente en la estructura) que indique qué tan grande debe ser el almacenamiento intermedio.Lo que nunca asignar uno de estos directamente, sino asignar el bloque de tamaño adecuado de la memoria, y luego echarlo:

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

El código es casi seguro que exhibe un comportamiento indefinido, de alguna manera, y no hay manera de solucionar este problema, excepto para arreglar la interfaz o el código fuente del SDK. Como ya no está en el negocio, esto es imposible.

+0

Técnicamente, tienes razón, es UB. Siendo realistas, el hack de estructura ha sido lo suficientemente común durante el tiempo suficiente que las posibilidades de obtener resultados inesperados cuando lo usa "correctamente" son esencialmente inexistentes. Es poco probable que esto cambie con la mayoría de los compiladores, ya que C99 y posteriores lo bendicen como un "miembro de arreglo flexible". –

+0

No creo que esta respuesta tenga sentido en contexto. "UB" elimina las restricciones sobre cómo un compilador arbitrario puede manejarlo. Pero sabemos que la biblioteca está compilada con VC6 y nunca se compilará con otro compilador, por lo que el comportamiento ya está escrito en piedra. – MSalters

Cuestiones relacionadas