memcpy_s c arrays sizeof memcpy

memcpy_s - memcpy(), ¿cuál debería ser el valor del parámetro de tamaño?



memset (12)

Quiero copiar una matriz int a otra matriz int. Usan la misma definición para la longitud, por lo que siempre serán de la misma longitud.

¿Cuáles son las ventajas y desventajas de las siguientes dos alternativas del parámetro size para memcpy ()?

memcpy(dst, src, ARRAY_LENGTH*sizeof(int));

o

memcpy(dst, src, sizeof(dst));

¿La segunda opción siempre funcionará? ¿Independientemente del contenido?

Una cosa que favorece a la última es que si se cambiara la matriz, sería una tarea de mantenimiento del hogar actualizar los memcpy ().

Gracias


¿La segunda opción siempre funcionará? ¿Independientemente del contenido?

La segunda opción solo funciona si se agregaron nuevamente las que faltan ) y dst es una matriz estática (es decir, de tipo int[123] ).

Si dst tiene un tamaño desconocido (es decir, int[] ), sizeof dst solo devuelve el tamaño del puntero, ya que dst ha reducido a un puntero. En este caso, debe usar sizeof(*dst)*ARRAY_LENGTH .


¿La segunda opción siempre funcionará? ¿Independientemente del contenido?

Solo funcionará si se cumplen ambas condiciones:

  • dst es una matriz regular, no puntero
  • src y dst son del mismo tamaño

memcpy (), ¿cuál debería ser el valor del parámetro de tamaño?

Debe ser el mínimo entre el tamaño del búfer de origen y el tamaño del búfer de destino.

Tradicionalmente, el tamaño del búfer de origen ha sido utilizado. Eso desbordó el búfer de destino en ocasiones ... Por lo tanto, es mejor usar una versión "más segura" de la función: una que especifique los tamaños del búfer de origen y de destino.

Tiene funciones "más seguras" disponibles a través de ISO / IEC TR24731 . Hay mucho más que hacer, como valores de retorno consistentes y un comportamiento de manejo de cadenas consistente.

Las funciones "más seguras" son parte del estándar C ahora, por lo que se supone que están disponibles en todas partes. Así que deberías usar memcpy_s .

No puede usarlo en Linux, ya que no proporciona las funciones (no crea que la exageración de marketing sobre el cumplimiento de estándares)). En Linux, debe "enrollar su propio" envoltorio.

No todos son fanáticos de las funciones más seguras. Vea, por ejemplo, ¿Utiliza las funciones ''seguras'' de TR 24731? . Sobre todo lo que puedo decir sobre esto es: múltiples desbordamientos de búfer de libunp . Millones de enrutadores y puertas de enlace están sujetos a múltiples vulnerabilidades y muchos permanecen sin parchear. Y se debieron a errores que habrían sido detenidos por las funciones más seguras. +1 a todos los que están diciendo "no uses esta mierda de Microsoft".


¿Qué tal si?

memcpy(dst, src, &src[ARRAY_LENGTH] - &src[0]);

Esto debería funcionar incluso si el tamaño de los elementos individuales fuera más pequeño que el tamaño tomado por cada elemento en la matriz real.


Depende. Tanto arr como pointer son matrices, pero sizeof () solo devuelve el tamaño correcto para arr, que se declara en el momento de la compilación.

int main() { int arr[10]; int * pointer; pointer = (int *) malloc(10 * sizeof(int)); printf("%d/n", sizeof(arr)); // 40 printf("%d/n", sizeof(pointer)); // 4 or 8 free(pointer); }


Mientras dst se declare como una matriz con un tamaño, sizeof devolverá el tamaño de esa matriz en bytes:

int dst[ARRAY_LENGTH]; memcpy( dst, src, sizeof(dst) ); // Good, sizeof(dst) returns sizeof(int) * ARRAY_LENGTH

Si dst simplemente resulta ser un puntero al primer elemento de dicha matriz (que es del mismo tipo que la propia matriz), no funcionará:

int buffer[ARRAY_LENGTH]; int* dst = &buffer[0]; memcpy( dst, src, sizeof(dst) ); // Bad, sizeof(dst) returns sizeof(int*)


Si ha asignado utilizando malloc, debe indicar el tamaño de la matriz

int * src = malloc(ARRAY_LENGTH*sizeof(*src)); int * dst1 = malloc(ARRAY_LENGTH*sizeof(*dst)); memcpy(dst1,src,ARRAY_LENGTH*sizeof(*dst));

Si ha asignado una matriz estática, puede usar sizeof

int dst2[ARRAY_LENGTH]; memcpy(dst2,src,sizeof(dst2));


Si se asignó dst desde el montón (utilizando malloc, por ejemplo), la segunda solución no funcionará. sizeof (dst) solo funcionará cuando el compilador lo sepa. Por ejemplo, el siguiente ejemplo fallará ya que sizeof (dst) será igual al tamaño de un puntero (4-8 bytes).

#define ARRAY_LENGTH 10 int *dst; dst = malloc(ARRAY_LENGTH*sizeof(int)); memcpy(dst, src, sizeof(dst)); // sizeof dst in this case would be 4 bytes on 32 bit system

Este segmento de código funcionará siempre:

#define ARRAY_LENGTH 10 int *dst; dst = malloc(ARRAY_LENGTH*sizeof(int)); memcpy(dst, src, ARRAY_LENGTH*sizeof(int)); // sizeof would be 40 bytes


Si y cuando tiene una matriz (real) puede usar el truco sizeof(array) , pero tenga en cuenta que si refactoriza el código y lo empuja en algún lugar donde la matriz se haya convertido en un puntero (o si la memoria se asignó inicialmente en un puntero (malloc / nuevo) deberá pasar un tamaño conocido.

Ignorar los tamaños relativos de origen y destino, es decir, suponiendo que sean los mismos para el resto de la discusión, si está utilizando C ++, le recomendaría un truco de metaprogramación que le dará un recuento de tamaño seguro para los arreglos y fallará. compila si intentas usarlo con punteros:

template <typename T, int N> inline int array_memory_size( T (&a)[N] ) { return sizeof a; }

De esa manera:

int main() { int array[10]; int *ptr = array; int orig[10] = { 0 }; memcpy( array, orig, array_memory_size(array) ); // ok //memcpy( ptr, orig, array_memory_size(ptr) ); // compilation error }

Si en cualquier momento refactoriza y el código se mueve a un lugar donde la matriz ha decaído (o si reemplaza una matriz estática por una asignada dinámicamente), el compilador le dirá que necesita corregir el cálculo de tamaño.


Suponiendo que dst es del tipo int *, sizeof (dst) devolverá el tamaño del propio puntero (es decir, 4 en un sistema de 32 bits, 8 en un sistema de 64 bits), por lo que su segundo ejemplo solo copiará este número de bytes, mientras que el primero utilizará correctamente el tamaño real del contenido.


sizeof (X) siempre te da el NÚMERO DE BYTES de "X" si X es una matriz uint16_t de 10, entonces sizeof (X) devolverá 20

uint16_t X[10]={0}; cout<<"sizeof x: "<<sizeof(X); $> sizeof x: 20

Si desea la cantidad de elementos que tiene que hacer un poco de aritmética de bytes:
8 bits = 1 byte
16 bits = 2 bytes
32 bits = 4 bytes
64 bits = 8 bytes

para obtener la cantidad de elementos que podrías hacer:

numb_of_elements = ( sizeof(X)/sizeof(X[0]) );

Resultando en:

uint32_t source[100]={0}; memcpy((void*) dest, (void*) source, ( sizeof(source)/sizeof(source[0]) ));

por supuesto, probablemente querrá hacer que (sizeof (X) / sizeof (X [0])) sea una constante / variable para no calcular cada vez ... (No sé si los compiladores siempre optimizarán esto)


sizeof(dst) es correcto solo si dst es una matriz cuyo tamaño se conoce en tiempo de compilación: como int arr[ARRAY_LENGTH] o una matriz de longitud variable C99; de lo contrario, devuelve el tamaño de un puntero, no la longitud de la matriz de destino.

Para evitar errores futuros, sea coherente y prefiera la primera forma: tamaño de tipo * longitud.