8
votes

Les threads peuvent-ils être créés en toute sécurité lors de l'initialisation statique?

À un moment donné, je me souviens de lire que les threads ne peuvent pas être créés en toute sécurité avant la première ligne de principale (), car les compilateurs insérent du code spécial pour effectuer des travaux de filetage qui s'exécute pendant la période d'initialisation statique. Donc, si vous avez un objet global qui crée un fil sur la construction, votre programme peut se bloquer. Mais maintenant, je ne trouve pas l'article original et je suis curieux à quel point une restriction est forte - est-ce strictement vraie par la norme? Est-ce vrai sur la plupart des compilateurs? Restera-t-il vrai en C ++ 0x? Est-il possible pour un compilateur conforme aux normes de faire initialisation statique elle-même multithreadé? (par exemple, détecter que deux objets globaux ne se touchent pas et les initialisez-les sur des threads distincts pour accélérer le démarrage du programme)

Edit: Pour clarifier, j'essaie d'au moins avoir une idée de si les implémentations diffèrent considérablement à cet égard, ou si c'est une pseudo-standard. Par exemple, techniquement, la norme permet de mélanger la disposition des éléments appartenant à différents spécificateurs d'accès (public / protégé /, etc.). Mais aucun compilateur que je ne connaisse en fait cela.


1 commentaires

"Est-ce strictement vrai par la norme" - la norme C ++ 03 n'a rien à dire sur le sujet des fils. Les endroits pour regarder en ce qui concerne le comportement actuel seraient POSIX (ce qui est bien sûr A Standard, tout simplement pas la norme standard), MSDN, Boost ou tout autre spécifique de la mise en œuvre Docs pour le compilateur, la plate-forme et le filetage de l'API que vous utilisez.


3 Réponses :


6
votes

De quoi vous parlez n'est pas strictement dans la langue mais dans la bibliothèque de temps d'exécution C (CRT).
Pour un démarrage, si vous créez un fil à l'aide d'un appel natif tel que créatethread () sous Windows, vous pouvez le faire n'importe où que vous voudriez, car il va directement au système d'exploitation sans intervention du CRT. .
L'autre option que vous avez habituellement est d'utiliser _breginthread () qui fait partie du CRT. Il y a quelques avantages à utiliser _breginthread () comme ayant un filet-coffre-fort errco. En savoir plus à ce sujet ici . Si vous allez créer des threads à l'aide de _breginthread () Il pourrait y avoir des problèmes car les initialisations nécessaires pour _breginthread () ne sont pas en place.

Cela touche une question plus générale de ce qui se passe exactement avant principal () et dans quel ordre. Fondamentalement, vous avez la fonction de point d'entrée du programme qui prend soin de tout ce qui doit se produire avant principal () avec Visual Studio, vous pouvez réellement regarder cette pièce de code qui est dans le CRT et découvrez-vous pour vous-même. Qu'est-ce qui va exactement là-bas. Le moyen le plus facile d'arriver à ce code consiste à arrêter un point d'arrêt dans votre code et à regarder les cadres de pile avant principal ()


2 commentaires

Merci, cela me donne une idée de la situation de la situation sur Windows avec MSVC. Je ne suis toujours curieux d'autres plateformes cependant, et cela ne répond pas vraiment à ce que cela soit sûr sous Windows ou non (_BEGINTHREAD () comptez en réalité sur une initialisation qui peut ne pas avoir eu lieu?).


Je voudrais savoir aussi. Les documents ne semblent pas en parler.



2
votes

Le problème sous-jacent est une restriction de Windows sur ce que vous pouvez et ne peut pas faire en dllmain. En particulier, vous n'êtes pas censé créer des threads dans DllMain. L'initialisation statique arrive souvent de DllMain. Ensuite, il s'ensuit logiquement que vous ne pouvez pas créer de threads lors de l'initialisation statique.


2 commentaires

Mais Remarque: lors de la démarrage de processus et des routines d'initialisation DLL, de nouveaux threads peuvent être créés, mais ils ne commencent pas à exécuter que l'initialisation de la DLL ne soit effectuée pour le processus de msdn.microsoft.com/en-us/library/ms682453%28V=VS.85%29 .aspx


Point juste, n'avait pas vu cela. Notez que le commentaire s'applique spécifiquement à Createthread cependant, _breginthreadex n'a pas cette exception.



0
votes

Autant que je puisse dire de lire le brouillon C ++ 0x / 1x, démarrer un thread avant principal () est bien, mais toujours soumis aux pièges normaux de l'initialisation statique. Une implémentation conforme devra s'assurer que le code pour supporter le threading exécute avant tout constructeur statique ou de fil.


0 commentaires