siguiente extracto de aquí

pw = (widget *)malloc(sizeof(widget));

asigna almacenamiento en bruto. De hecho, la llamada malloc asigna almacenamiento
que sea lo suficientemente grande y adecuadamente alineados a sostener un objeto de tipo
widget de

ver también rápido pImpl de herb sutter, dijo:

Alineación. Cualquier memoria de Alineación. La memoria que se le asignó
dinámicamente a través de nuevos o malloc está garantizado para estar correctamente alineado para
objetos de cualquier tipo, pero los búferes de que no se asignan de forma dinámica
no tienen ninguna garantía de

Estoy curioso acerca de esto, ¿cómo malloc saber la alineación de tipo personalizado?

  • nuevo y de malloc, por defecto, alinear la dirección de 8 bytes (x86) o de 16 bytes (64), que es el óptimo para la mayoría de datos complejos. También es sizeof() deber de obtener el tamaño correcto struct por interior acolchado para la alineación, si es necesario.
InformationsquelleAutor Chang | 2012-01-06

6 Comentarios

  1. 47

    Los requisitos de alineación son recursivos: La alineación de cualquier struct es simplemente el más grande de la alineación de cualquiera de sus miembros, y esto se entiende de forma recursiva.

    Por ejemplo, y suponiendo que cada uno de los fundamentales del tipo de alineación es igual a su tamaño (esto no es siempre cierto en general), la struct X { int; char; double; } tiene la alineación de double, y será acolchado para ser un múltiplo del tamaño de la doble (por ejemplo, 4 (int), 1 (char), 3 (relleno), 8 (doble)). El struct Y { int; X; float; } tiene la alineación de X, que es el más grande e igual a la alineación de double, y Y se sentó en consecuencia: 4 (int), 4 (relleno), 16 (X), 4 (float), 4 (de relleno).

    (Todos los números son sólo ejemplos y pueden diferir en su máquina.)

    Por lo tanto, descomponiéndolo a los tipos fundamentales, sólo necesitamos saber de un puñado de fundamental alineaciones, y entre los que hay un conocido más grande. C++, incluso define un tipo de max_align_t cuya alineación es que la alineación más grande.

    Todos malloc() que necesita hacer es elegir una dirección que es un múltiplo de ese valor.

    • La clave de lo que hay que señalar es que esto no incluye personalizada align directivas del compilador que podría sobre-la alineación de datos.
    • Aunque si el uso de estas que ya están fuera del alcance de la norma, por favor, tenga en cuenta que la memoria asignada en este camino, probablemente, no cumplir con los requisitos de alineación para tipos como _m256 que están disponibles como extensiones en algunas plataformas.
    • ¿Qué sucede cuando se especifica una costumbre de alineación a través de alignas que es más grande que el más grande de la alineación de un tipo de datos primitivo?
    • Apoyo para la alineación extendida es la aplicación definida.
    • std::max_align_t es la alineación más grande de tipos escalares, de modo que una estructura o una clase puede tener más estricto requisito de alineación de std::max_align_t.
    • Sí, pero sólo si se le da un alignas, ¿verdad? De lo contrario, un UDT alineación se acaba de hacer de forma recursiva de la alineación de los miembros.
    • Sí, pero algunos ampliamente utilizados clases de la biblioteca estándar podría ser más alineados en algunas plataformas. F. ex. consulte este problema. También clases virtuales incluyen un puntero a una tabla virtual para su alineación no sólo está determinada por la alineación de los miembros.

  2. 21

    Creo que la parte más relevante de la Herb Sutter cita es la parte que más me ha marcado en negrita:

    Alineación. Cualquier memoria de Alineación. La memoria que se asigna de forma dinámica a través de nuevos o malloc está garantizado para estar correctamente alineados para objetos de cualquier tipo de, pero búferes de que no se asignan de forma dinámica no tienen ninguna garantía de

    No tiene que saber de qué tipo usted tiene en mente, porque es la alineación para cualquier tipo. En cualquier sistema, hay un máximo de tamaño de alineación que jamás necesaria o significativa; por ejemplo, un sistema con cuatro bytes, palabras probablemente tendrá un máximo de cuatro bytes de alineación.

    Esto también es claro por el malloc(3) hombre-página, que dice en parte:

    La malloc() y calloc() funciones devuelven un puntero a la memoria asignada que está debidamente alineado para cualquier tipo de variable.

    • cuál es el significado de cualquier tipo de variable? esto no responde a mi pregunta. qué significa malloc siempre use el máximo tamaño de alineación en cualquier sistema dado, ¿verdad?
    • efectivamente, sí. Tenga en cuenta también, la cita está mal. new sólo está garantizado para tener «cualquier» alineación a la hora de asignar char o unsigned char. Para otros, puede tener una alineación menor.
    • A la derecha, el máximo tamaño de alineación. «Convenientemente alineados para cualquier tipo de variable» significa «convenientemente alineados para un int y adecuadamente alineados para un puntero y adecuadamente alineados para cualquier struct y . . .».
    • char[16] no garantiza la alineación en todo. (En general, new T[n] devuelve un puntero alineados para cualquier tipo de X donde sizeof(X)<=sizeof(T).)
    • Eso no es cierto. Ver el C++11 spec, sección 5.3.4, cláusula 10; new char[16] se especifica en un camino que supone la garantía de que está debidamente alineado para cualquier tipo de X donde sizeof(X)<=16.
    • No, new T[n] es sólo alineados para el tipo de T, a menos que T es (posiblemente signed/unsigned) char, entonces es alineados para cualquier tipo de X donde sizeof (X) <= n.
    • Um, sí. De alguna manera consiguió varios muy equivocado ideas a partir de la observación en el mismo párrafo Estándar. La comprensión de la lectura fallar.
    • Creo que la «magia de la alineación» es sólo para char y unsigned char, pero NO para signed char. El C++ spec trata char y unsinged char como «byte» tipos, pero no cnosider signed char un «byte» de tipo. (Implícitamente, la especificación no decir realmente «byte tipos» como tal.)
    • Parece que tienes razón, pero creo que puede ser un defecto en la Norma, ya que el acompañamiento de la nota habla sobre genérico matrices de caracteres, que incluye los tres: «esta restricción en la matriz de asignación de sobrecarga permite que el común lenguaje de la asignación de matrices de caracteres en el que los objetos de otros tipos va a ser colocados» (Y que tenga a su vez probablemente debería decir secuencias de caracteres, desde que matrices de caracteres incluir distintos tipos de caracteres así)
    • Me gustaría plantear que fue el defecto, ya que unsigned char se utiliza en byte-al igual que las formas de §3.8/5-6 §3.9/2-4, §3.10/10, y §5.3.4/10, y en ninguno de esos es signed char mencionados o implícita. También, §3.9/1 llama unsinged char específicamente con «todos los posibles patrones de bits de la representación de valor representan los números».

  3. 5

    La única información que malloc() puede utilizar es el tamaño de la petición que se ha pasado. En general, se podría hacer algo como ronda el pasado de tamaño más cercana a la mayor (o igual) potencia de dos, y alinear la memoria basado en ese valor. Existe la probabilidad de ser también un límite superior en el valor de alineación, como 8 bytes.

    La de arriba es una hipotética discusión, y la implementación real depende de la arquitectura de la máquina y de la biblioteca de tiempo de ejecución que estás usando. Tal vez su malloc() siempre devuelve bloques alineados en 8 bytes y nunca ha hacer algo diferente.

    • En resumen, malloc utiliza el «peor caso» de la alineación porque no conocen nada mejor. Eso no significa que calloc puede ser más inteligente, ya que toma dos argumentos, el número de objetos y el tamaño de un objeto?
    • Tal vez. Tal vez no. Tendrías que buscar en tu biblioteca de tiempo de ejecución fuente para averiguar.
    • -1, lo siento. Su respuesta incluye la verdad, pero también incluye la desinformación. No es un «tal vez, tal vez no» cosa»; es específicamente documentados para trabajar en una forma que no depende del tamaño. (No sé porque no, sin embargo. Parece que no tendría un sentido perfecto para hacerlo.)
    • La respuesta a mi propia pregunta es No. He encontrado este: «malloc() y calloc() funciones devuelven un puntero a la memoria asignada que está debidamente alineado para cualquier tipo de variable.» Parecer el memalign función es potencialmente útil, sin embargo: wwwcgi.lect.ac.reino unido:8081/cgi-bin/cgiwrap/wsi14/poplog/hombre/3C/…
    • ver ruakh la respuesta, por lo que malloc siempre use el máximo tamaño de alineación en cualquier sistema dado, ¿verdad?
  4. 3

    1) Alinee el mínimo común múltiplo de todas las alineaciones. por ejemplo, si ints requiere 4 bytes de la alineación, pero los punteros requieren 8, a continuación, asignar todo a 8 bytes de alineación. Esto hace que todo esté alineado.

    2) Utilice el tamaño de argumento para determinar la alineación correcta. Para los tamaños pequeños se puede inferir el tipo, tales como malloc(1) (suponiendo que otros tipos de tamaños no son 1) es siempre un char. C++ new tiene la ventaja de ser el tipo de seguro y también lo hará la alineación de las decisiones de esta manera.

    • Se puede ampliar el acrónimo LCM? Puedo adivinar, pero yo no tengo por qué.
    • También, hay otros tipos en C++ que puede ser de 1 byte. Sin embargo, su implicación es correcta, puede alinear basado en el tamaño del tipo.
  5. 2

    Anterior a la de C++11 alineación fue tratado bastante simple mediante la alineación más grande donde el valor exacto se desconoce y malloc/calloc todavía funcionan de esta manera. Esto significa malloc asignación está correctamente alineado para cualquier tipo de.

    Alineación indebida puede provocar un comportamiento indefinido de acuerdo a la norma, pero he visto x86 compiladores de ser generoso y sólo castigando con menor rendimiento.

    Tenga en cuenta que usted también puede ajustar la alineación a través de las opciones del compilador o directivas. (pragma pack para VisualStudio por ejemplo).

    Pero cuando se trata de la colocación de la nueva, luego C++11 nos trae nuevas palabras clave llamado alignof y alignas. Aquí está el código que muestra el efecto si compilador max alineación es mayor que 1. La primera la colocación de la nueva a continuación es automáticamente buena, pero no la segunda.

    #include <iostream>
    #include <malloc.h>
    using namespace std;
    int main()
    {
    struct A { char c; };
    struct B { int i; char c; };
    unsigned char * buffer = (unsigned char *)malloc(1000000);
    long mp = (long)buffer;
    //First placment new
    long alignofA = alignof(A) - 1;
    cout << "alignment of A: " << std::hex << (alignofA + 1) << endl;
    cout << "placement address before alignment: " << std::hex << mp << endl;
    if (mp&alignofA)
    {
    mp |= alignofA;
    ++mp;
    }
    cout << "placement address after alignment : " << std::hex <<mp << endl;
    A * a = new((unsigned char *)mp)A;
    mp += sizeof(A);
    //Second placment new
    long alignofB = alignof(B) - 1;
    cout << "alignment of B: " <<  std::hex << (alignofB + 1) << endl;
    cout << "placement address before alignment: " << std::hex << mp << endl;
    if (mp&alignofB)
    {
    mp |= alignofB;
    ++mp;
    }
    cout << "placement address after alignment : " << std::hex << mp << endl;
    B * b = new((unsigned char *)mp)B;
    mp += sizeof(B);
    }

    Supongo que el rendimiento de este código puede ser mejorado con algunas operaciones a nivel de bit.

    EDIT: se ha Sustituido caro modulo de cálculo con operaciones a nivel de bit. Aún con la esperanza de que alguien encuentre algo aún más rápido.

    • En realidad, no es el compilador, es el mismo hardware. En x86 desviados de acceso a la memoria simplemente obliga al procesador a buscar a los dos lados de la memoria de límites y la pieza el resultado en conjunto, por lo que siempre es «correcto» si es más lento. Por ejemplo, en algunos procesadores ARM, se obtendría un error de bus y la caída de un programa. Esto es un poco de un problema debido a que muchos programadores nunca están expuestos a cualquier otra cosa que x86, por lo que no puede saber que el comportamiento es en realidad indefinido, en lugar de simplemente disminuyendo el rendimiento.
    • Estás en lo correcto, su hardware o de la cpu del software, pero no el compilador real que guarda usted en la arquitectura x86. Realmente me pregunto por qué no hay más convenientes api para manejar esto. Como si de C/C++ diseñadores querían que los desarrolladores de paso en la trampa. Me recuerda a std::numeric_limits<doble>::min() de la trampa. Alguien tiene que se una bien la primera vez?
    • Bien, una vez que usted sepa lo que está pasando, no es demasiado duro para cambiar su estilo de programación de todo tipo de loco de tipo descriptivo para bien escrito el código, afortunadamente. El tipo C del sistema hace que sea bastante fácil para conservar la alineación de tipo como usted no ir haciendo el loco de manipulación de bits de cosas sin prestar atención. Ahora puntero-aliasing libre de código en el otro lado tiene algunos mucho más duro de la semántica…
    • Yo no lo entiendo. Usted tiene el problema cada vez que usted tiene su propio pequeño montón de que te las arreglas tú mismo. Lo que el uso de la colocación de nuevo estás pensando en tu comentario?
  6. 0

    malloc no tiene conocimiento de lo que es la asignación, debido a que su parámetro es simplemente el total de tamaño.
    Sólo se alinea con una alineación que es seguro para cualquier objeto.

Dejar respuesta

Please enter your comment!
Please enter your name here