Remplacement de Windows malloc (par exemple, tcmalloc) et liaison crt dynamic

Un programme C ++ qui utilise plusieurs DLL et QT doit être équipé d’un remplacement malloc (tel que tcmalloc ) pour les problèmes de performances pouvant être vérifiés comme étant causés par Windows malloc. Avec Linux, il n’y a pas de problème, mais avec Windows, il y a plusieurs approches, et je ne trouve aucune d’entre elles intéressante:

1. Placez le nouveau malloc dans lib et assurez-vous de le lier en premier (Autre question SO)

Cela présente l’inconvénient que, par exemple, strdup utilisera toujours l’ancien malloc et qu’un programme gratuit risque de faire planter le programme .

2. Supprimez malloc de la bibliothèque statique libcrt avec lib.exe (Chrome)

Ceci est testé / utilisé (?) Pour chrome / chrome , mais a l’inconvénient de fonctionner uniquement avec des liens statiques avec le crt. La liaison statique pose problème si une bibliothèque système est liée dynamicment à msvcrt, il peut y avoir des incohérences dans l’allocation / désallocation de tas . Si je le comprends bien, tcmalloc pourrait être lié dynamicment de sorte qu’il y ait un tas commun pour toutes les DLL auto-compilées (ce qui est bien).

3. Patch code source crt (firefox)

Jemalloc de Firefox corrige apparemment le code source de Windows CRT et construit un nouveau crt. Cela a encore le problème de liaison statique / dynamic ci-dessus.

On pourrait penser à utiliser ceci pour générer un MSVCRT dynamic, mais je pense que ce n’est pas possible, car la licence interdit de fournir un MSVCRT avec le même nom.

4. Mise à jour dynamic du CRT chargé au moment de l’exécution

Certains allocateurs de mémoire commerciaux peuvent faire une telle magie. tcmalloc peut faire aussi, mais cela semble plutôt moche. Il y avait des problèmes, mais ils ont été corrigés. Actuellement, avec tcmalloc, il ne fonctionne pas sous Windows 64 bits.

Y a-t-il de meilleures approches? Des commentaires?

Q: Un programme C ++ divisé sur plusieurs DLL doit:

A) remplacer malloc?

B) s’assurer que l’allocation et la désaffectation se font dans le même module dll?

R: La réponse correcte est B. Une conception d’application c ++ qui incorpore plusieurs DLL DEVRAIT s’assurer qu’un mécanisme existe pour garantir que les éléments qui sont alloués sur le tas en une dll sont libérés par le même module dll.


Pourquoi voudriez-vous diviser un programme c ++ en plusieurs DLL? Par programme c ++, je veux dire que les objects et les types que vous traitez sont des modèles c ++, des objects STL, des classes, etc. Vous NE POUVEZ PAS transmettre des objects c ++ sans avoir une conception soignée et beaucoup de magie spécifique au compilateur. de la duplication massive du code object dans les différents fichiers dll, et par conséquent une application extrêmement sensible à la version. Toute modification mineure apscope à une définition de classe forcera la reconstruction de tous les exe et dll, supprimant au moins l’un des principaux avantages d’une approche dll de développement d’applications.

Adhérez à une interface C droite entre app et dll, souffrez en enfer, ou comstackz simplement l’application c ++ complète en un seul exemple.

C’est une affirmation audacieuse qu’un programme C ++ “devrait être équipé d’un remplacement malloc (comme tcmalloc) pour les problèmes de performance ….”

“[Sur] 6 sur 8 benchmarks populaires … [applications de taille réelle] remplaçant l’allocateur personnalisé, dans lequel les gens avaient investi beaucoup de temps et d’argent, … avec l’atsortingbut idiot fourni par le système [produit] de meilleures performances … Les allocateurs personnalisés les plus simples, adaptés à des situations très spéciales, sont les seuls à pouvoir apporter des gains. ” – Andrei Alexandrescu

La plupart des allocateurs de systèmes sont aussi bons qu’un allocateur à usage général . Vous pouvez faire mieux que si vous avez un modèle d’allocation très spécifique.

En règle générale, ces modèles spéciaux ne s’appliquent qu’à une partie du programme, auquel cas il est préférable d’appliquer l’allocateur personnalisé à la partie spécifique pouvant en bénéficier plutôt que de remplacer globalement l’allocateur.

C ++ fournit quelques moyens de remplacer sélectivement l’allocateur. Par exemple, vous pouvez fournir un allocateur à un conteneur STL ou vous pouvez remplacer nouveau et supprimer une classe par classe. Les deux vous donnent un bien meilleur contrôle que tout hack qui remplace globalement l’allocateur.

Notez également que le remplacement de malloc et de free ne changera pas nécessairement l’allocateur utilisé par les opérateurs new et delete. Bien que l’opérateur new global soit implémenté en utilisant malloc, il n’est pas nécessaire qu’il le fasse. Donc, remplacer malloc pourrait ne pas affecter la plupart des allocations.

Si vous utilisez C, il y a de fortes chances que vous puissiez envelopper ou remplacer les clés malloc et les appels gratuits par votre allocateur personnalisé, à l’endroit de votre choix, et laisser le rest du programme utiliser l’allocateur par défaut. (Si ce n’est pas le cas, vous voudrez peut-être envisager un remaniement.)

Les allocateurs de système ont des décennies de développement derrière eux. Ils sont stables et bien testés. Ils fonctionnent extrêmement bien pour les cas généraux (en termes de vitesse brute, de contention de thread et de fragmentation). Ils ont des versions de débogage pour la détection des fuites et la prise en charge des outils de suivi. Certains améliorent même la sécurité de votre application en fournissant des défenses contre les vulnérabilités de saturation de la mémoire tampon. Il est probable que les bibliothèques que vous souhaitez utiliser ont été testées uniquement avec l’allocateur de système.

La plupart des techniques pour remplacer l’allocateur de système perdent ces avantages. Dans certains cas, ils peuvent même augmenter la demande de mémoire (car ils ne peuvent pas être partagés avec le runtime DLL éventuellement utilisé par d’autres processus). Ils ont également tendance à être extrêmement fragiles face aux changements de la version du compilateur, de la version d’exécution et même de la version du système d’exploitation. L’utilisation d’une version modifiée du moteur d’exécution empêche les utilisateurs de bénéficier des mises à jour d’exécution fournies par le fournisseur du système d’exploitation. Pourquoi abandonner tout cela en conservant ces avantages en appliquant un atsortingbut personnalisé à la partie exceptionnelle du programme qui peut en bénéficier?

D’où vient votre prémisse “Un programme C ++ qui utilise plusieurs DLL et QT devrait être équipé d’un remplacement malloc”

Sous Windows, si toutes les DLL utilisent le MSVCRT partagé, il n’est pas nécessaire de remplacer malloc. Par défaut, Qt se construit sur la DLL partagée MSVCRT.

On se heurtera à des problèmes si:

1) mélanger les DLL qui utilisent la liaison statique par rapport au VCRT partagé

2) ET également de la mémoire libre qui n’était pas allouée d’où elle venait (c’est-à-dire de la mémoire libre dans un dll lié de manière statique qui avait été alloué par le VCRT partagé ou vice versa).

Notez que l’ajout de votre propre wrapper compté de références autour d’une ressource peut aider à atténuer les problèmes associés aux ressources qui doivent être libérées de manière particulière (par exemple, un wrapper disposant d’un type de ressource via un rappel à la DLL d’origine, différent wrapper pour une ressource provenant d’une autre DLL, etc.).

nedmalloc? NB également que smplayer utilise un patch spécial pour remplacer malloc, qui peut être la direction dans laquelle vous vous êtes dirigé.