c++ - examples - ¿Por qué a Malloc() le importan las alineaciones de los límites?
malloc sizeof (6)
La memoria asignada se alineará de acuerdo con el tipo de datos del puntero.
Si estás hablando de malloc
, esto es falso. malloc
no le importa lo que haga con los datos y asignará la memoria alineada para que se ajuste al tipo nativo más estricto de la implementación.
Del estándar:
El puntero devuelto si la asignación tiene éxito se alinea adecuadamente para que pueda asignarse a un puntero a cualquier tipo de objeto con un requisito de alineación fundamental y luego se utiliza para acceder a dicho objeto o una matriz de tales objetos en el espacio asignado (hasta que el espacio está explícitamente desasignado)
Y:
Lógicamente, ¿por qué es importante que el límite de la dirección en sí sea divisible en
Debido al funcionamiento de la máquina subyacente, acceder a los datos no alineados podría ser más costoso (por ejemplo, x86) o ilegal (por ejemplo, armar). Esto permite que el hardware tome accesos directos que mejoran el rendimiento / simplifican la implementación.
He oído que malloc()
alinea la memoria según el tipo que se está asignando. Por ejemplo, del libro Understanding and Using C Pointers :
La memoria asignada se alineará de acuerdo con el tipo de datos del puntero. Por ejemplo, un número entero de cuatro bytes se asignaría en un límite de dirección uniformemente divisible por cuatro.
Si sigo, esto significa que int *integer=malloc(sizeof(int));
se asignará en un límite de dirección uniformemente divisible por cuatro. Incluso sin conversión (int *)
en malloc.
Estaba trabajando en un servidor de chat; Leí un efecto similar con struct
s.
Y tengo que preguntar: lógicamente, ¿por qué es importante que el límite de la dirección en sí sea divisible? ¿Qué hay de malo con la asignación de un grupo de memoria a la melodía de n*sizeof(int)
usando un número entero en la dirección 129
?
Sé cómo funciona la aritmética de puntero *(integer+1)
, pero no puedo descifrar la importancia de los límites ...
Depende del hardware. Incluso suponiendo que int
es de 32 bits, malloc(sizeof(int))
podría devolver una dirección divisible entre 1, 2 o 4. Los diferentes procesadores manejan el acceso no alineado de forma diferente.
Los procesadores ya no leen directamente de la RAM, eso es demasiado lento (lleva cientos de ciclos). Entonces, cuando agarran RAM, la toman en grandes pedazos, como 64 bytes a la vez. Si su dirección no está alineada, el entero de 4 bytes puede estar a horcajadas en dos líneas de caché de 64 bytes, por lo que su procesador tiene que hacer dos cargas y corregir el resultado. O quizás los ingenieros decidieron que no es necesario construir el hardware para reparar las cargas desalineadas, por lo que el procesador señala una excepción: el programa se bloquea o el sistema operativo detecta la excepción y arregla la operación (cientos de ciclos desperdiciados).
Alinear direcciones significa que su programa funciona bien con el hardware.
En muchos procesadores, los datos que no están alineados causarán una "trampa" o "excepción" (esta es una forma diferente de excepción que aquellas entendidas por el compilador C ++. Incluso en procesadores que no atrapan cuando los datos no están alineados) , por lo general, es más lento (el doble de lento, por ejemplo) cuando los datos no están alineados correctamente. Por lo tanto, está en el mejor interés de la biblioteca / tiempo de ejecución del compilador asegurarse de que las cosas estén bien alineadas.
Y por cierto, malloc
(típicamente) no sabe lo que está asignando. Insteat, malloc
alineará TODOS los datos, sin importar su tamaño, con un límite adecuado que sea "suficientemente bueno" para el acceso general a los datos, generalmente 8 o 16 bytes en las combinaciones modernas de OS / procesador, 4 bytes en sistemas antiguos.
Esto es porque malloc
no sabrá si haces char* p = malloc(1000);
o double* p = malloc(1000);
, por lo que debe suponer que está almacenando el double
o lo que sea que sea el elemento con el mayor requisito de alineación.
La cita del libro es incorrecta; la memoria devuelta por malloc
está garantizada para alinearse correctamente para cualquier tipo. Incluso si escribe char *ch = malloc(37);
, todavía está alineado para int
o cualquier otro tipo.
Parece que estás preguntando "¿Qué es la alineación?" Si es así, ya hay varias preguntas sobre SO sobre esto, por ejemplo here , o una buena explicación de IBM here .
La importancia de la alineación no es un problema de lenguaje sino de hardware. Algunas máquinas son incapaces de leer un valor de datos que no está alineado correctamente. Otros pueden hacerlo, pero lo hacen de manera menos eficiente, por ejemplo, requieren dos lecturas para leer un valor desalineado.
Porque es más rápido; A la mayoría de los procesadores les gustan los datos que están alineados. Incluso, ¡Algunos procesadores NO PUEDEN acceder a datos que no están alineados! (Si intenta acceder a estos datos, el procesador puede ocurrir un error)