2010-06-22 5 views
1

Mon programme a une classe avec un vecteur de Level objets nommés levels. En fonction de membre il y a cette ligne:erreur étrange en g ++

levels.push_back(level::Level()); 

J'ai fait plusieurs changements à mon programme aujourd'hui, et cette ligne de code a commencé segfaulting:

0x0804d248 in void std::vector<yarl::level::Level, std::allocator<yarl::level::Level> >::emplace_back<yarl::level::Level>(yarl::level::Level&&) (this=0x0, 
__args#0=...) at /usr/include/c++/4.4/bits/vector.tcc:93 
93  if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) 

Je pensais que l'objet Level peut-être en quelque sorte devenir corrompu, donc je déclarais à l'extérieur l'appel de fonction pour que je puisse l'inspecter dans gdb, comme ceci:

level::Level foo(); 
levels.push_back(foo); 

Transforme ce ne compile pas. Il g ++ donne deux erreurs que je ne l'ai pas vu auparavant:

error: invalid conversion from 'level::Level (*)()' to 'int' 
error: initializing argument 1 of 'level::Level::Level(int, int, int)' 

Maintenant, le constructeur de Level prend trois paramètres entiers, chacun avec des valeurs par défaut. Je pensais que l'on aurait pu se plaindre que je ne l'avais pas passé ces trois paramètres, même si elles ont par défaut, alors j'ai changé la première ligne pour passer la valeur des paramètres par défaut:

level::Level foo(1, 100, 100); 

Cette compile maintenant, et encore segfaults, mais le fait à un endroit différent (même si un test identique):

0x0804c699 in std::vector<yarl::level::Level, std::allocator<yarl::level::Level> >::push_back (this=0x0, __x=...) at /usr/include/c++/4.4/bits/stl_vector.h:735 
735  if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) 

Je sais que cela est trop peu de code pour vous attendre les gars d'être en mesure de résoudre mon problème, mais peut-être que quelqu'un pourrait me dire un peu plus sur ce que ces erreurs signifient? Ces erreurs g ++ en particulier; Je ne sais pas pourquoi il n'accepterait pas un constructeur Level vide étant donné que tous ses paramètres sont par défaut, et je n'ai aucune idée de ce que signifie la partie (*)() de l'erreur (cela rend l'erreur très frustrante pour google).

+6

'niveau :: Niveau foo();' est une fonction déclaration; Si vous voulez appeler le constructeur par défaut, omettez simplement les parenthèses. –

+1

Niveau Niveau Niveau int int int, cela ressemble à un chant étrange. :-) – Omnifarious

+0

@Rob, ma négligence. supprimé –

Répondre

2
level::Level foo(); 

qui déclare une fonction nommée foo qui ne prend aucun argument et renvoie une level::Level. Ceci est connu comme the most vexing parse. Cela crée un level::Level en utilisant le constructeur par défaut:

level::Level foo; 

Quant à votre problème d'origine, vous semblez avoir un pointeur NULL this:

... ::push_back (this=0x0, __x=...) ... 

Cela pourrait se produire si levels est une référence à null. Avez-vous créé la référence en déréférençant un pointeur nul?

+0

Un pointeur nul en g ++ est généralement provoqué par l'utilisation d'un objet supprimé. – Jay

+0

'levels' est un membre sans pointeur d'une classe, déclaré comme' std :: vector niveaux 'dans la définition de la classe. Y a-t-il un moyen de rendre null le pointeur 'this' d'un membre non-pointeur? – Max

+0

J'ai trouvé le problème. La classe dont 'levels' fait partie appartenait à un' tr1 :: shared_ptr' que j'oubliais d'initialiser, donc 'levels' serait certainement nul. Merci de m'avoir indiqué la bonne direction, tout le monde. – Max

1

Je n'ai aucune idée de ce que signifie la partie (*)() de l'erreur (cela rend l'erreur très frustrante pour google).

code comme ceci:

Object obj(); 

ne crée pas une instance d'objet appelé obj et par défaut initialiser. Il déclare une fonction sans paramètre qui renvoie une instance Object. Apparemment, votre vecteur n'est pas conçu pour contenir des pointeurs sur de telles fonctions.

Le reste de vos problèmes sont dus à un manque d'opérateur serviette sur la ligne 42.

5

Au moins l'une des erreurs est assez simple. Ce:

level::Level foo(); 

est une erreur assez commune en C++ connu sous le nom most vexing parse. Vous ne déclarez pas une variable avec le nom foo et le type level::Level, vous êtes en train de déclarer une fonction avec ce nom et un type de retour qui ne prend aucun argument.Supprimez les parenthèses pour déclarer une variable

Vos autres appels échouent parce que (comme indiqué dans la trace de la pile) this est NULL, mais ce n'est pas évident pour moi pourquoi cela, d'autant plus que vous semblez opérer sur une variable de pile et non un pointeur

+0

J'ai toujours pensé que "l'analyse la plus vexante" se référait spécifiquement à l'affaire "T x (T())" et non à la plus générale "T x();" –

+0

@James Oh, éventuellement; Je pensais que cela couvrait les deux mais je ne sais pas grand-chose à ce sujet –

+0

Oh. Droite. Je le savais, je le jure. – Max

0

Vous devez lire sur les attentes de la collection STL pour leurs arguments basés sur des modèles. Ils s'attendent au minimum à ce que les arguments du modèle de type d'élément aient un comportement "valeur". Un int a un comportement de valeur parce que si vous avez

int a; // default constructor works 

Puis

a = 3; // assignment works 
int c(a); // copy construction works 

la classe std :: vecteur travaillera avec des objets qui ont un opérateur d'affectation surchargé et un constructeur de copie. std :: map et certaines autres collections ont besoin d'autres choses comme des surcharges d'opérateurs de comparaison.

est ici une classe avec un constructeur de copie, un constructeur par défaut, et une surcharge de l'opérateur d'affectation:

class foo 
{ 
private: 
    int m_internalVal; 
public: 
    foo() : m_internalVal(0) { } 
    foo(const foo& other) : m_internalVal(other.m_internalVal) { } 
    foo& operator =(const foo& rval) { m_internalVal = rval.m_internalVal; return *this; } 
}; 
+0

'Level' utilise le constructeur de copie par défaut et les opérateurs d'affectation que le compilateur écrit, donc je suis raisonnablement sûr que ce n'est pas un problème avec la façon dont la classe est écrite. En fait, la poussée du vecteur a fonctionné pendant environ un mois, jusqu'à aujourd'hui. – Max

+0

Si la classe Level ne contient pas de pointeurs, de poignées ou d'autres entités avec une sémantique de référence (ce qui peut entraîner des doubles suppressions si Level implémente la sémantique de propriété et possède un constructeur/opérateur de copie par défaut) . –