Est-il une garantie d'alignement de l'adresse de retour par le C++'s nouvelle opération?
Plus de programmeur expérimenté sait alignement des données est important pour la performance du programme. J'ai vu un programmeur écrit le programme qui allouent une plus grande taille de la mémoire tampon qu'ils ont besoin, et utiliser le alignés pointeur que commencer. Je me demande dois-je faire dans mon programme, je n'ai aucune idée de quelles sont les garanties de l'alignement de l'adresse retournée par le C++'s nouvelle opération. J'ai donc écrit un petit programme pour tester
for(size_t i = 0; i < 100; ++i) {
char *p = new char[123];
if(reinterpret_cast<size_t>(p) % 4) {
cout << "*";
system("pause");
}
cout << reinterpret_cast<void *>(p) << endl;
}
for(size_t i = 0; i < 100; ++i) {
short *p = new short[123];
if(reinterpret_cast<size_t>(p) % 4) {
cout << "*";
system("pause");
}
cout << reinterpret_cast<void *>(p) << endl;
}
for(size_t i = 0; i < 100; ++i) {
float *p = new float[123];
if(reinterpret_cast<size_t>(p) % 4) {
cout << "*";
system("pause");
}
cout << reinterpret_cast<void *>(p) << endl;
}
system("pause");
Le compilateur, je suis à l'aide de Visual C++ Express 2008. Il semble que toutes les adresses de la nouvelle opération retournés sont alignés. Mais je ne suis pas sûr. Donc ma question est: est-il garanti? Si elles ont la garantie, je n'ai pas à aligner moi-même, si ce n'est, je dois le faire.
Vous devez vous connecter pour publier un commentaire.
L'alignement a la garantie suivante de la norme (3.7.3.1/2):
MODIFIER: Grâce à timday pour la mise en évidence d'un bug dans gcc/glibc où la garantie ne tient pas.
EDIT 2: Ben commentaire souligne un intéressant cas de bord. Les exigences sur l'allocation des routines sont ceux fournis par la norme uniquement. Si l'application a sa propre version, alors il n'y a pas de garantie sur le résultat.
operator new[]()
helper fonction d'allocation, qui à cette exigence concerne, n'est pas le même pointeur que vous obtenez de lanew[]
de l'opérateur. Cette réponse est fausse.operator new[]()
est bien aligné. Maisnew T[n]
n'y est pas tenu et n'a généralement pas, retouroperator new[](n * sizeof (T))
. Presque chaque compilateur ajoute des métadonnées en face de suivre le nombre d'éléments (de sorte que le nombre de destructeurs sont appelés), et coller une tête en face de toute évidence des modifications de l'alignement.char
(ouunsigned char
)the new-expression yields a pointer to the initial element (if any) of the array
. Doncnew[]
est le retour de l'élément du tableau - et pas seulement un emplacement de mémoire. Il doit donc avoir un alignement correct etc.new[]
est pas le même que pour un alignement optimal. Pour des raisons de performances, vous voulez que certaines structures alignées dans le cache. En tant que tel, même si vous mettez à jour votre réponse citer la section appropriée de la Norme, il ne peut toujours pas répondre à la question posée. Aussi, certaines instructions (notamment ESS) require, plus strictes, de l'alignement.C'est une réponse tardive mais juste pour clarifier la situation sur Linux sur les systèmes 64 bits
la mémoire est toujours de 16 octets alignés:
http://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html
La
new
opérateur appelsmalloc
en interne(voir
./gcc/libstdc++-v3/libsupc++/new_op.cc
)si cela s'applique à
new
ainsi.La mise en œuvre de
malloc
qui fait partie de laglibc
fondamentalement définitMALLOC_ALIGNMENT
être2*sizeof(size_t)
etsize_t
est 32 bits=4byte et 64 bits=8bytesur un x86-32 et x86-64, respectivement.
D'ailleurs le MS documentation mentionne quelque chose à propos de malloc/nouveau retour des adresses qui sont de 16 octets alignées, mais à partir de l'expérimentation, ce n'est pas le cas. Il m'est arrivé d'avoir besoin de l'16 octets d'alignement pour un projet (à la vitesse de la mémoire des copies avec un renforcement de l'instruction), en fin de compte, j'ai eu recours à l'écriture de mon propre allocateur...
La plate-forme nouvelles/[nouveau] de l'opérateur sera de retour pointeurs avec suffisamment d'alignement de sorte qu'il va faire de la bonne à la base les types de données (en double,float,etc.). Au moins raisonnable compilateur C++ de+runtime devrait le faire.
Si vous avez des exigences alignement comme pour l'ESS, alors il est probablement une bonne idée d'utiliser des aligned_malloc fonctions, ou rouler vos propres.
J'ai travaillé sur un système où ils ont utilisé l'alignement afin de libérer de l'étrange pour leur propre usage!
Ils ont utilisé l'impair de bits à mettre en œuvre un système de mémoire virtuelle.
Lorsqu'un pointeur eu l'étrange jeu de ils ont utilisé que pour signifier qu'elle a fait (moins l'étrange
bits) à l'information pour obtenir les données de la base de données et non les données.
Je pense que c'est une particulièrement méchant bits de codage, ce qui était loin d'intelligent pour son propre bien!!
Tony
C++17 modifie les exigences sur la
new
allocateur, tel qu'il est obligé de retourner un pointeur dont l'alignement est égale à la macro__STDCPP_DEFAULT_NEW_ALIGNMENT__
(qui est définie par la mise en œuvre, en incluant un en-tête).Ceci est important parce que cette dimension peut être plus que
alignof(std::max_align_t)
. Dans Visual C++ par exemple, le maximum de l'alignement régulier est de 8 octets, mais le défautnew
retourne toujours 16 octets aligné mémoire.Notez également que si vous remplacez la valeur par défaut
new
avec votre propre allocateur, vous êtes nécessaire à respecter les__STDCPP_DEFAULT_NEW_ALIGNMENT__
ainsi.new
le fait automatiquement quand le type a de nouveau étendu à l'alignement.