2017-09-15 1 views
13

J'ai lu dans beaucoup d'endroits (par exemple here) au sujet des personnes obtenant une erreur de "méthode virtuelle pure appelée" et un accident de programme à runtime. This answer dit queDans quelles conditions le stub de méthode virtuelle pure est-il généré?

La plupart des compilateurs attribuent ces entrées vtable à un talon qui émet une erreur avant d'abandonner le programme.

et this one indique même que Itanium ABI spécifie ce qu'est ce bout.

Le problème est: toutes mes tentatives pour voir ce comportement en action sont interceptées par le compilateur (GCC 6.4.1) à l'heure de compilation comme références non définies. Par exemple, lorsque vous appelez une fonction virtuelle pure à partir d'un constructeur de la classe abstraite, je reçois un avertissement

pure virtual ‘virtual int X::f()’ called from constructor

mais en même temps tout simplement pas de code du tout est généré pour X::f() si cela est suivi par

undefined reference to 'X::f()'

de l'éditeur de liens et la compilation échoue. Cela semble une manière assez infaillible d'empêcher l'erreur à l'exécution. Dans quelle situation mon compilateur aurait-il besoin de générer le talon mentionné ci-dessus? Ou est-il devenu assez intelligent pour détecter suffisamment tôt toutes les situations pathologiques possibles?

+3

Il n'a jamais nécessaire pour générer le talon. L'appel d'une méthode virtuelle pure est un comportement indéfini. Certains compilateurs profitent de la nature permissive du comportement indéfini pour vous en offrir un par courtoisie. –

Répondre

10

Habituellement, il sera appelé indirectement à l'intérieur d'un constructeur. Voici un exemple minimal:

#include <iostream> 

struct X { 
    virtual void foo() = 0; 
    void bar() { foo(); } 
    X() { bar(); std::cout << "X"; } 
}; 

struct Y : X { 
    void foo() override {} 
}; 


int main() { 
    Y y; 
    return 0; 
} 

Le compilateur est obligé de lier l'appel si statiquement il apparaît à l'intérieur du c'tor directement (et peut donc produire un message d'erreur utile pour une fonction virtuelle pure). Mais lorsque l'appel est indirect, d'un autre membre, il doit être envoyé de manière dynamique.

Naturellement, la partie Y n'a pas encore été construit lors de la construction de X, de sorte que le tout s'effondre dans un incendie lui-même d'un comportement non défini.

Live example - With the stub at work

+0

Je suis surpris que le compilateur ne se plaint pas d'avoir appelé une méthode virtuelle du constructeur. – Steve

+3

@Steve - Mais nous n'appelons pas une fonction virtuelle du c'tor. Pas directement. Et il est difficile de vérifier si nous en appelons indirectement. – StoryTeller

+0

Ah. Cela a du sens. Merci de clarifier. – Steve