9
votes

__attribute __ ((constructeur)) Confusion de commande d'appel

La réponse Voici démontre que __attribute __ ((constructeur)) n'est pas Appelé après forte> initialisation statique, il est appelé dans l'ordre de déclaration.

Ensuite, quel est le but de celui-ci, s'il n'est pas garanti d'être appelé lorsque toutes les données sont initialisées? Nous pourrions aussi bien avoir notre code ((constructeur)) dans le constructeur FOO. P>

Ce que je recherche est un moyen d'avoir, dans une bibliothèque partagée, un code qui sera exécuté après tout Statique Les données sont initialisées et les constructeurs statiques sont appelés. J'ai vu des personnes recommandant __attribute __ ((constructeur)) en remplacement de DLLMain; Comme nous pouvons le voir, c'est faux, car certaines données statiques ne peuvent toujours pas être initialisées. P>

Bien sûr dans un fichier unique (unité de compilation), nous pourrions organiser des statiques. Mais dans un programme typique, il y a beaucoup de fichiers. Existe-t-il un moyen de garantir que ((constructeur)) dans un fichier sera définitivement appelé après que toutes les autres statiques dans une bibliothèque partagée sont initialisées? P>

Si je mettez un fichier avec une initialisation statique (constructeur, objet, etc) à la fin de la ligne de commande GCC: P>

g++ -shared -fPIC source1.o source2.o MyLastInitChance.o


9 commentaires

__ Attribut ((constructeur)) __ est plus logique pour Pure C, plutôt que C ++.


Vous pouvez également spécifier __attribute __ ((constructeur (0))) etc. Pour spécifier la commande Les fonctions sont appelées.


Malheureusement, la priorité 0 provoque l'appel d'abord, alors que j'en ai besoin pour être appelé en dernier. Les priorités plus élevées ne vous aident pas aussi.


Pourquoi ne DLLMAIN fonctionne-t-il pour vous?


Ce que j'aimerais faire est de porter un grand code Windows existant existant (qui utilise DLLMain) sans le changer.


@ H2CO3, les priorités inférieures à 101 sont réservées, ne les utilisez pas ! Les priorités peuvent aller jusqu'à 65535, n'utilisez rien en dessous de 101


@Jonathan, il est possible que la priorité 101 est cette optique?


Non, parce que Les numéros inférieurs indiquent une priorité plus élevée. (personne ne lit pas Documentation Ces jours-ci ?!) Peut-être la priorité 65535 de sorte qu'il fonctionne plus tard pas plus tôt. Mais je pense que cela ne va pas aider, même la priorité 65535 n'applique pas de commande par rapport à la statique dans d'autres unités de traduction.


Oui, 65535 signifie simplement "priorité par défaut".


4 Réponses :


2
votes

Le plus gros avantage de attribut (constructeur)) __ est la priorité associée à chaque bloc et aide spécifiquement votre cas.

Vous avez deux blocs de code qui ont un danger de données (un ensemble doit être exécuté en premier). Cela ne peut pas être atteint par un bloc statique unique. Utilisation d'un bloc statique et d'un attribut ((constructeur)) __ ne résoudra pas votre problème en raison de la confusion concernant la commande.

Le meilleur moyen de faire face au problème est d'avoir deux Attribut (constructeur)) __ avec deux priorités différentes. Déplacez votre bloc d'initialisation statique existant sur la priorité supérieure (0) et l'autre bloc de code à la priorité inférieure.


13 commentaires

Non, je peux utiliser des priorités uniquement pour mon code, pas pour les "autres" variables statiques.


Si vous ne pouvez pas modifier les "autres" variables statiques, il est préférable de ne pas implémenter la fonctionnalité du tout, car vous allez entraver la maintenabilité du code. Même si vous réalisez ce que vous essayez de réaliser avec un piratage, vous serez inondé de courir dur pour trouver des bugs. Modifiez votre conception ou changez l'autre code


Les deux solutions en gras ne répondent pas à ma question.


Je connais des réponses à d'autres questions.


J'ai peur de connaître la réponse à cette question aussi. Mais la réponse n'est pas ce que vous voulez être. La réponse est Non, vous ne pouvez pas commander l'attribut statique et constructeur . Vous devez savoir que votre question poser la question ne créera pas de nouvelle fonctionnalité, de mettre en œuvre une nouvelle fonctionnalité que vous devez rejoindre les contributeurs de la GCC et de mettre en œuvre les fonctionnalités, et c'est seulement après avoir convaincu toutes les autres que ce type de fonctionnalité est en fait nécessaire!


"Non que vous ne pouvez pas commander" - c'est faux parce qu'il y a la fonction de commande - déjà, et c'est init_priority. Mais je ne veux pas commander tous; Je veux seulement courir en dernier.


Vous êtes confus ... en cours d'exécution en premier / dernier est en fait appelé ordre d'exécution. Je serais mieux si vous fermez la question, car vous ne comprenez pas ce que vous demandez ...


Ordre d'exécution? Vous avez dit que je ne peux pas commander.


Quoi qu'il en soit, ce que je suis intéressé résolvez un problème particulier ou prouvant qu'il est impossible de résoudre. "Prouvage" signifie ici peu de citations et / preuve des relations publiques, pas seulement non.


1. Pour résoudre le problème , changez votre conception ou modifiez l'autre code . Avec l'attribut constructeur et la priorité initiale, vous devez faire de même
2. Ceci est un site QA non un site d'épreuve. Certaines des preuves nécessitent effectivement une thèse de maîtrise ou de doctorat.


Si la réponse est suffisamment complexe pour exiger une thèse, je ne l'obtiendrai probablement pas ici. Cela je peux comprendre. Je vais fermer la question est votre réponse va prouver que c'est le cas. Pour le moment, cela ne le fait pas.


La réponse pourrait être "Vous pouvez réorganiser la section des acateurs" (ce qui est ce que même les gens à Mozilla considérés comme faisaient), que je me suis retrouvé quelque temps après, encore une enquête (c'est pourquoi je demande également une preuve, par exemple peut-être. Une mauvaise idée). Une autre solution est probablement toujours possible. Si vous ne voulez pas perdre votre temps, ne répondez pas, c'est facile.


Vous risquez de réorganiser .Cables et, dans ce cas, cela ne devrait pas être si difficile à faire - regardez ma réponse.



2
votes

Voir ceci: http://gcc.gnu.org /ml/gcc-help/2011-05/msg00220.html et la réponse http://gcc.gnu.org/ml/gcc-help/2011-05/msg00221.html

en particulier citant de la réponse:

Tous les objets avec un attribut init_priority sont construits avant tout objet sans attribut init_priority.

Remarque Il est en fait sur __ attribut __ ((init_priority)) et pas sur __ attribut __ ((constructeur)) mais je crois qu'ils utilisent tous les deux le même code dans GCC, respectivement dans GNU Linker. Tout d'abord correspond à des objets C ++, c'est-à-dire appeler leur constructeur / destructeur, ce dernier concerne le marquage des fonctions spécifiques telles que le constructeur ou le destructeur.

IMHO, le __ attribut __ ((constructeur)) existe principalement à cause de C, pas C ++.


2 commentaires

Malheureusement, Init_Proiority provoque l'appel que mon code soit appelé en premier, alors que j'en ai besoin d'être appelé dernier. C'est la même solution que le constructeur (0), cela ne m'aident pas. Je ne peux pas configurer toutes les variables statiques dans tous les modules avec des attributs init_priority, c'est un non-sens.


Oui, mon message indique que vous ne pouvez pas l'utiliser à cet effet, à cause du texte en gras. Vous devriez attribuer la priorité à tous les autres objets statiques qui sont irréalistes.



13
votes

Vous pouvez essayer d'utiliser des scripts de liaison pour ld . Vous pouvez en savoir plus à ce sujet ici , mais je suppose que ce que vous recherchez est xxx

dans sections {...} bloc. Cela devrait réorganiser les sections . / Code> des sections de fichier afin que le fichier fourni appellera ses constructeurs comme le dernier. De toute évidence, des solutions plus avancées sont également disponibles si vous trouvez y a besoin d'yeyelf dans le besoin d'un;)

indice: écrire votre propre script de liaison est fastidieux. Utilisez ld 'S - option verbose qui imprime le script de liaison utilisé et le modifier. Ajoutez ensuite votre script de liaison en utilisant le commutateur -t .


2 commentaires

La prime se termine demain et je n'avais pas le temps d'expérimenter des scripts de likers, mais c'est proche de ce dont j'ai besoin et d'avoir l'air prometteur, merci. Je vais certainement vérifier cela.


Après des enquêtes Objdump, OBJDUMP donne à être vide (uniquement FFFFFFFFF), .init_array a des données mais ne semble pas être affectée par réarrangement. Je me demande si ce que je dois réorganiser est _ Ctor_List _ Data. Je pense que GCC met l'initialisation unique Func dans .init_array et ce func marche __ctor_list__.



2
votes

Pouvez-vous implémenter une "construction sur la première utilisation" de ce modèle global?

par exemple xxx

Il sera construit après toutes les ctors statiques ordinaires, mais avant tout Code régulier en a besoin.


2 commentaires

Oui, c'est un bon modèle, merci. Malheureusement, il n'y a pas d'objet ou de fonction unique qui sera appelé dans la bibliothèque partagée chargée que je peux utiliser ou envelopper dans gmagic () et être sûr que sera utilisé avant d'autres objets.


Votre objet initialement initialisé a-t-il des effets externes? Est-ce que cela doit être créé s'il n'est pas explicitement utilisé? Sinon, alors vous ne devriez pas vous inquiéter que ce n'est pas encore créé. Quand vous en avez besoin pour être créé, ce sera: D