usar resueltos nombres matriz leer imprimir funciones ejercicios ejemplos como caracteres cadenas cadena arreglo almacenar c++ char bytearray deserialization memcpy

c++ - resueltos - leer cadena de caracteres en c



No se puede memcpy correctamente una matriz de caracteres para estructurar (2)

Entonces tengo una construcción llamada paquete

struct Packet { unsigned int packet_type; wchar_t packet_length[128]; wchar_t file_name[256]; wchar_t template_name[256]; wchar_t file_name_list[1024]; wchar_t file_data[1024]; void serialize(char * dat) { memcpy(dat, this, sizeof(Packet)); } void deserialize(const char * dat) { memcpy(this, dat, sizeof(Packet)); } };

Estoy tratando de desieralizar de esta información

{byte[2692]} [0] 0 unsigned int packet_type; (4 bytes) [1] 0 [2] 0 [3] 0 [4] 50 ''2'' wchar_t packet_length[128]; (128 bytes) [3] 0 [5] 54 ''6'' [3] 0 [6] 57 ''9'' [3] 0 [7] 50 ''2'' [8] 0 [...] 0 [132] 112 ''p'' wchar_t file_name[256]; (256 bytes) [133] 0 [134] 104 ''h'' [...] 0

Pero la memcpy in deserialze no me da el nombre de archivo, pero sí me da el paquete_length. ¿Qué pasa con esto? ¡Gracias!

EDITAR: Ahora me queda claro que wchar_t está ocupando más espacio de lo que alguna vez pensé; sin embargo, me dicen que no use memcpy en absoluto?

He escrito este método de deserialización y toma los datos correctamente. ¿Seguirá causando esto una fuga de seguridad?

void deserialize(const char * dat) { memcpy(&(packet_type), dat, 4); memcpy(&(packet_length[0]), dat + 4, 128); memcpy(&(file_name[0]), dat + 132, 256); memcpy(&(template_name[0]), dat + 388, 256); memcpy(&(file_name_list[0]), dat + 644, 1024); memcpy(&(file_data[0]), dat + 1668, 1024); }


El diseño de su matriz char presupone que el tamaño de wchar_t es de dos bytes; no lo es - aquí hay un ejemplo de un sistema donde el tamaño de wchar_t es 4 , por lo que el tamaño del Packet es 10756 , no 2692 bytes: ( enlace a una demostración ).

Es por eso que su truco memcpy de la edición presenta un problema: asume que el diseño de los datos en la matriz char[] coincide con el diseño de las matrices wchar_t[] , que puede o no coincidir. Si sabe que su matriz de datos tiene elementos de dos caracteres almacenados en formato pequeño endian (LSB primero), puede escribir su propia función que convierta los datos de la fuente al destino y llamarlo por partes de sus datos serializados, como esta:

void bytes_to_wchar(wchar_t *dest, const unsigned char* src, size_t length) { for (size_t i = 0 ; i != lengt ; i++) { dest[i] = src[2*i] | (src[2*i+1] << 8); } }

Ahora puede usar esta función para copiar datos en matrices wchar_t independientemente del tamaño de wchar_t en el sistema de destino, o la endianidad del sistema de destino:

void deserialize(const char * dat) { bytes_to_wchar(packet_type, dat + 0, 4); bytes_to_wchar(packet_length[0], dat + 4, 128); bytes_to_wchar(file_name[0], dat + 132, 256); bytes_to_wchar(template_name[0], dat + 388, 256); bytes_to_wchar(file_name_list[0], dat + 644, 1024); bytes_to_wchar(file_data[0], dat + 1668, 1024); }

El acceso directo de guardar los datos de la memoria y volver a escribirlos puede funcionar cuando lo hace en el mismo hardware, utilizando el mismo compilador. Incluso entonces sigue siendo sensible a los pequeños ajustes en los encabezados que utiliza y en la configuración del compilador.

Si el conjunto de caracteres que necesita copiar en la struct tiene un diseño fijo, debe escribir una función para procesar ese diseño, convirtiendo grupos de dos bytes en wchar_t s, grupos de cuatro bytes en unsigned int , y así sucesivamente.


Por favor, no use este método para serializar estructuras. Es completamente no portátil.

Además, el compilador también podría rellenar, alinear o reordenar miembros en función de la arquitectura de destino, endianness, optimizaciones y un montón de otras cosas.

Una forma mucho más elegante sería usar boost :: Serialization , que se encarga de los detalles de bajo nivel de una manera portátil.

Si, por otro lado, solo quieres inspeccionar tus estructuras, entonces un depurador es útil ...