Dans l'ABI x86-64, les types int128 et long double sont supposés être placés sur une limite de 16 octets.
Cependant, l'implémentation pymalloc de Python est conçue pour renvoyer des blocs de mémoire avec des limites de 8 octets. .. .. Est-ce que ça va? Si vous essayez de malloc une structure contenant un type qui nécessite un alignement de 16 octets, il doit être un multiple de 16 octets, donc malloc (sizoef (structure)) est sûr, et malloc (sizeof (structure) + nombre d'octets qui n'est pas un multiple de 16) ) Semble poser un problème dans de tels cas.
Le plus problématique est l'en-tête GC. L'en-tête GC dans un environnement 64 bits est de 24 octets. Comme le nom "en-tête" l'indique, il est placé au début des objets cibles GC (objets pouvant constituer des références circulaires, telles que tuple, liste, dict, etc.).
Lors de la création d'un objet cible GC, allouez de la mémoire comme malloc (sizeof (en-tête GC) + taille de l'objet)
puis utilisez l'adresse décalée par l'en-tête GC pour un pointeur de type PyObject *
. Ainsi, même si malloc renvoie une adresse de limite de 16 octets, l'objet Python sera stocké à l'adresse + 24 octets, et si la structure de l'objet a un type double int128 ou long, il sera placé à travers la limite de 16 octets. Je vais.
Il semble que les compilateurs récents utilisent en fait des instructions qui supposent des limites de 16 octets, et au lieu de "violer théoriquement mais fonctionnant en fait sans problèmes", le problème est "de tomber en segfo". Il est devenu.
Je ne l'ai remarqué que récemment, mais Python 2.7 a signalé ce comportement plus tôt et 2.7.15 a augmenté l'en-tête GC de 24 octets à 32 octets. (changelog, [commit](https://github.com/python/cpython/ commit / 0b91f8a668201fc58fa732b8acc496caedfdbae0), issue)
Un problème similaire a été récemment signalé dans Python 3.7 (Crash issue, [Old ubsan error issue](https: //bugs.python.). org / issue27987)) Il semble donc que nous devrons appliquer le même correctif à moins que nous ne trouvions un autre bon moyen de ne pas rompre la compatibilité ABI. Pour les types rares tels que long double et int128, il est regrettable pour moi, qui suis stupide, de devoir augmenter la consommation de mémoire de taples volumineux et ne contenant jamais ces types de +8 octets.
À propos, dans Python 3.8, le contenu de l'en-tête GC est réduit de 3 mots (24 octets dans un environnement 64 bits) à 2 mots (16 octets dans le même), et l'utilisation de la mémoire des objets cibles GC str, bytes, int, float, etc. est réduite à 8. J'ai réussi à couper la morsure. Par conséquent, il n'est pas affecté par ce problème et aucun remplissage supplémentaire n'est requis. Le résultat est une réduction de 16 octets par rapport à Python 2.7.15 ou version ultérieure et peut-être 3.7.4 ou version ultérieure. Je suis vraiment content que cette amélioration ait réussi.
Recommended Posts