Un compilateur peut-il optimiser les allocations de mémoire du tas ?
Considérez le code C simple suivant qui alloue de la mémoire à l'aide du nouvel opérateur :
int main() { int* mem = new int[100]; return 0; }
Le compilateur peut-il optimiser le nouvel appel, évitant ainsi la mémoire dynamique allocation ?
Comportement du compilateur
Différents compilateurs se comportent différemment dans cette situation. g et Visual Studio 2015 n'optimisent pas le nouvel appel, contrairement à clang, comme observé dans les tests avec les optimisations complètes activées.
Raison d'être de l'optimisation du compilateur
Selon N3664 : Clarifiant l'allocation de mémoire, qui est devenue plus tard une partie de C 14, le compilateur est autorisé à optimiser les allocations de mémoire. Cette optimisation est basée sur l'hypothèse que le nouvel appel n'a pas d'effets secondaires observables.
Règle comme si
Cependant, la règle comme si dans le projet La section 1.9 de la norme C requiert des implémentations conformes pour émuler le comportement observable de la machine abstraite. Lancer une exception à new aurait des effets secondaires observables, on pourrait donc affirmer que le compilateur n'est pas autorisé à optimiser le nouvel appel.
Détails de l'implémentation
On d'un autre côté, on pourrait faire valoir que la décision de savoir quand lever une exception à la nouveauté est un détail de mise en œuvre. Clang pourrait potentiellement déterminer que l'allocation ne provoquerait pas d'exception et donc éluder le nouvel appel sans violer la règle du "comme si".
Allocations sans lancement
Utilisation du la version non lancée de new, new (std::nothrow) int[100], permet toujours à clang d'optimiser l'allocation. En effet, clang peut être en mesure de prouver qu'il n'existe pas d'opérateur de remplacement global new qui pourrait provoquer un comportement observable.
Optimisation agressive
Dans les versions antérieures de clang, même des optimisations plus agressives ont été effectuées, comme le montre ce code :
#include <cstddef> extern void* operator new(std::size_t n); template<typename T> T* create() { return new T(); } int main() { auto result = 0; for (auto i = 0; i < 1000000; ++i) { result += (create<int>() != nullptr); } return result; }
Ce code a été optimisé à :
main: # @main movl 00000, %eax # imm = 0xF4240 ret
Effectivement, toute la boucle a été optimisée. Les versions ultérieures de clang n'effectuent pas d'optimisations aussi agressives.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!