Question

Ceci est assez étrange pour moi, mais je reçois un défaut de segmentation inattendu et aléatoire lorsque je lance mon programme. Quelques fois ça marche, quelques fois il se bloque .. Le débogueur de Dev-C ++ me pointe vers une ligne du fichier: stl_construct.h

/**
   * @if maint
   * Constructs an object in existing memory by invoking an allocated
   * object's constructor with an initializer.
   * @endif
   */
  template<typename _T1, typename _T2>
    inline void
    _Construct(_T1* __p, const _T2& __value)
    {
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 402. wrong new expression in [some_]allocator::construct
     -> ::new(static_cast<void*>(__p)) _T1(__value);
    }

J'utilise la STL largement par la voie .. Que dois-je faire pour détecter l'origine du segfault? Y a-t-il des outils qui peuvent aider? Quelles sont les raisons qui peuvent conduire à des plantages aléatoires comme ça.

Edit:

Mon programme compte environ 5000 lignes de code. Je ne sais pas ce morceau de code que je dois montrer pour obtenir de l'aide car je n'ai aucune idée sur l'origine du problème, tout ce que je suis arrivé du débogueur est qu'il doit faire avec le TSL.

Edit:

J'ai déménagé à Code::Blocks maintenant, voici la pile d'appel:

#0 00464635 std::_Construct<std::pair<double const, int>, std::pair<double const, int> >(__p=0xb543e8, __value=@0x10) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_construct.h:81)
#1 00462306 std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_M_create_node(this=0x406fe50, __x=@0x10) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:367)
#2 00461DA7 std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_M_clone_node(this=0x406fe50, __x=0x0) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:379)
#3 004625C6 std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_M_copy(this=0x406fe50, __x=0x0, __p=0x406fe54) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:1029)
#4 00462A9D std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_Rb_tree(this=0x406fe50, __x=@0xb59a7c) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:559)
#5 0045A928 std::map<double, int, std::less<double>, std::allocator<std::pair<double const, int> > >::map(this=0x406fe50, __x=@0xb59a7c) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_map.h:166)
#6 0040B7E2 VehicleManager::get_vehicles_distances(this=0xb59a50) (C:/Program Files/CodeBlocks/MinGW/projects/AHS/VehicleManager.cpp:232)
#7 00407BDA Supervisor::IsMergeInstruction(id_vehicle=1) (C:/Program Files/CodeBlocks/MinGW/projects/AHS/Supervisor.cpp:77)
#8 00408430 CheckingInstructionsThread(arg=0x476100) (C:/Program Files/CodeBlocks/MinGW/projects/AHS/Supervisor.cpp:264)
#9 00413950 _glfwNewThread@4() (??:??)
#10 75A24911    KERNEL32!AcquireSRWLockExclusive() (C:\Windows\system32\kernel32.dll:??)
#11 00476100    std::__ioinit() (??:??)
#12 0406FFD4    ??() (??:??)
#13 76E5E4B6    ntdll!RtlInitializeNtUserPfn() (C:\Windows\system32\ntdll.dll:??)
#14 00476100    std::__ioinit() (??:??)
#15 70266582    ??() (??:??)
#16 00000000    ??() (??:??)

A quelques precisions:

1 / Il est une application multi-thread. 2 / La méthode: get_vehicles_distances (); retourne une carte. 3 / Il est possible que la carte ne soit pas initalised par le moment où il est appelé par IsMergeInstruction ();

Edit:

Apparemment, la ligne qui est à l'origine du segfault est:

vehicles_distances_.erase(vehicles_distances_.begin(), vehicles_distances_.end());

Où vehicles_distances_ est la carte. Cette ligne est une partie de la méthode: VehicleManager :: MoveAllVehicles ();

void VehicleManager::MoveAllVehicles() {

     vehicles_distances_.erase(vehicles_distances_.begin(), vehicles_distances_.end());

     vector<Vehicle>::iterator iter_end = VehicleManager::vehicles_.end();
     for(vector<Vehicle>::iterator iter = VehicleManager::vehicles_.begin();
     iter != iter_end; ++iter) {

          (*iter).MoveVehicle();

          vehicles_distances_[(*iter).get_vec_vehicle_position().y] = (*iter).get_id_vehicle();

     }

}

Quel est le problème avec ça?

Edit:

J'ai essayé d'utiliser la carte :: clear (); en remplacement de la carte :: effacement (); mais le même problème se produit!

Edit:

Je pense que je l'obtenir ... Un fil tente de faire une utilisation de vehicles_distances_ alors qu'il est autorisé .. (?)

Edit:

Problème résolu! Donc, il provenait de la carte :: effacement (); comme prévu. i le problème en contournais créant une autre variable de carte où la paire <key, value> a été inversée afin que je puisse mettre à jour la carte. (Puisque la clé que j'ai besoin est la distance, et la distance n'est pas unique car il change à chaque fois, mais le id_vehicle est unique!). A la fin, je viens de prendre cette carte, inversé la <key, value> à nouveau et transféré à la carte originale qui peut être redéclaré dans chaque cycle ...

Merci à tous!

Était-ce utile?

La solution

Tout d'abord, pour l'amour de tout ce qui est, bien, aimable, ne pas utiliser Dev-C ++ . Je voudrais savoir comment les gens continuent à courir dans ce morceau de ferraille. Il n'a pas été maintenue pour années , et même quand il a été maintenu, il était encore un morceau buggy d'ordure qui manquait une fonctionnalité très basique. Laissez tomber, et aller à l'une des innombrables alternatives plus libres.

Maintenant, sur votre question: Votre programme au hasard parce que vous avez fait quelque chose d'illégal de plus tôt. Ne pas faire cela. ;)

si votre programme écrit quelque part en dehors des limites, tout peut arriver. Il pourrait frapper une page non alloué, auquel cas vous obtenez une erreur de segmentation. Ou il pourrait frapper des données non utilisées sur une page qui est allouée à votre processus auquel cas il n'aura aucun effet pratique (à moins qu'il ne soit correctement initialisé après, votre premier remplaçant, illégal, écrire, et vous essayez de lire ce , attendant la valeur (invalide) d'origine d'être encore là. Ou il pourrait frapper des données qui est effectivement utilisé, dans ce cas, vous obtenez des erreurs plus tard, lorsque le programme tente de lire ces données.

A peu près les mêmes scénarios existent lors de la lecture des données. Vous pouvez être chanceux et obtenir un segfault immédiatement, ou vous pouvez frapper la mémoire inutilisée et non initialisée, et lire les données ordures (qui engendreront très probablement une erreur plus tard, lorsque ces données est utilisé), ou vous pouvez lire à partir des adresses de mémoire qui sont déjà en cours d'utilisation (ce qui vous donnera également garbage out).

Alors oui, ces erreurs sont difficiles à trouver. Le meilleur conseil que je peux donner est à 1) Saupoudrez affirme tout votre code pour assurer invariants de base sont maintenus, et 2) les étapes du programme, et à chaque étape, vérifiez que vous n'êtes pas lire ou écrire aux adresses n » t vous appartenir.

MSVC a une option SCL sécurisée activée par défaut qui effectuera la vérification des limites sur le code STL, ce qui peut aider à repérer des erreurs comme ça.

Je crois que GCC a une possibilité de faire quelque chose de similaire (mais ce n'est pas activé par défaut).

segfaults sont méchants. Une fois que les gens ont été mordus par une erreur comme ça quelques fois, ils ont tendance à devenir beaucoup plus disciplinée en évitant l'accès à la mémoire hors limites. :)

Autres conseils

Vous pouvez essayer Valgrind comme un moyen d'aider à trouver le problème. Compte tenu de la ligne que vous avez mis dans la question, je dois deviner que vous avez soit corrompu le tas, ou si vous avez un problème de pile.

La question évidente serait « ce qui est _p ». Dans le débogueur, vous devriez être en mesure de regarder le callstack. Suivre _p à son origine. Confirmer sa taille correcte, qu'il n'a pas été supprimé, et qu'il existe en fait.

Si ce n'est pas facile, il y a toujours les méthodes de force brute de commentaires sur le code aléatoire (présumé) jusqu'à ce qu'il fonctionne ou retourner et contre une copie diffing de travail connu,.

Ceci est incroyablement vague, il est presque impossible de répondre. Une suggestion évidente serait de vérifier si vous initialiser toutes vos variables. Certains compilateurs zéro votre truc non initialisée dans le débogage et ne pas faire que dans la version par exemple, conduisant à des résultats aléatoires et inattendus.

Vous pouvez utiliser _CrtSetDbgFlag() au au début de votre programme pour permettre des options de débogage en tas. Voir aussi Le CRT de débogage Heap . Cela peut vous aider à découvrir d'où vous faites de mauvaises choses avec la mémoire. Il est disponible dans le runtime C de Microsoft, qui vous les liens du compilateur MinGW contre par défaut. Si vous au lieu d'utiliser le moteur d'exécution de GNU C, alors vous ne pourrez pas aller dans cette voie.

Le problème est beaucoup plus susceptible d'être dans votre code que dans stl_construct.h. Je suppose que le fichier fait partie de la distribution de STL pour Dev-C ++. Le défaut de segmentation peut se produire dans le code qui a été instancié à l'aide des modèles dans stl_construct.h, mais la cause fondamentale du problème va être ailleurs. Je voudrais essayer de résoudre ce problème en obtenant la trace de la pile au moment de l'accident. Pour chaque fonction dans la trace de la pile (en particulier les ceux qui sont nouvellement écrites), essayez d'examiner le code et rechercher les types d'erreurs possibles suivantes:

  • Les variables non initialisées (indices en particulier utilisés pour l'accès au tableau)
  • Mémoire utilisée après qu'il a été libéré ou supprimé.
  • Accès Array en dehors des limites du tableau
  • L'allocation de mémoire qui est utilisée sans contrôle pour NULL (pas un problème si vous utilisez de nouveau parce que cela ne retourne pas NULL, il renvoie une exception)

Votre description et la pile d'appel, donnent à penser que le programme se bloque lors de l'initialisation des variables statiques. Ceci est un piège commun de C ++. Il n'y a aucun moyen simple de contrôler l'ordre d'initialisation des variables statiques

Par exemple, votre programme peut avoir foo d'objet qui dépend de l'objet bar; mais il se peut que le programme appelle le constructeur de foo avant qu'il construit bar. Ce serait mauvais, et pourrait causer le genre de problème que vous décrivez. (Est-CheckingInstructionsThread une variable statique qui engendre un fil? Cela pourrait être le problème là.)

Pour résoudre ce problème, vous pourriez avoir besoin de regarder à travers votre fichiers .cpp de programme pour les variables statiques (y compris la statique et la classe globals), en particulier ceux qui sont d'un certain type de classe. Il peut ou ne peut pas aider à modifier vos constructeurs d'écrire quelques traces à stderr; utiliser fprintf plutôt que cerr si vous le faites.

EDIT : Si vous n'êtes pas sûr si elle n'a rien à voir avec statics, essayez de mettre une ligne comme celui-ci au début de main():

 fprintf(stderr, "main() entered\n");

Ce ne serait pas exclure l'initialisation statique comme la cause du problème; même si elle ne le fait pas plantage avant main(), vous pouvez toujours avoir des structures de données étant mis en place de manière incorrecte. Mais, si vous n'arrivez à la fprintf, alors vous sais que l'initialisation statique est la cause.

qu'est-ce que la trace de la pile vous dire après avoir exécuté le débogueur avec le fichier de base? exécuter gdb de façon normale GDB a.out

examiner le fichier de base

  

a.out.core de base

Et jetez un oeil à la pile

  

bt

Ceci est très probablement liée à invalidée iterator - recherche de lieux où vous itérer sur des conteneurs et / ou garder itérateurs dans des conteneurs et supprimer / insérer des éléments en même temps
Et comme tout le monde a noté -. Utiliser un Call- pile pour trouver l'endroit exact.

La première chose que vous devez faire quand vous finissez dans le code qui a été testé à fond qui ne vous appartient pas va la pile d'appel jusqu'à ce que vous vous retrouvez dans votre propre code, vous trouverez les informations qui a causé ce problème arriver.

Dans l'appel pile l'endroit le plus important de regarder est à votre code (l'appelant) et les paramètres transmis à la fonction que vous avez appelé (l'appelé).

Sans ces informations, nous ne pouvons pas vous aider plus. ; -)

En savoir plus sur les défauts de segmentation: http://en.wikipedia.org/wiki/Segmentation_fault
(Il faut lire, voir aussi les liens à « Voir aussi » et « liens externes »)

cartes ne sont pas fil très convivial. Si vous effectuez des opérations de carte dans le code de fil que vous avez vraiment besoin de verrouiller tous les accès à cette carte et de réaliser des itérateurs vous tenir pourrait être invalidée.

Il ressemble à une fonction dangereuse:)

Une chose me bien barré. Où va la mémoire allouée? Intuitivement, je voudrais avoir un pointeur vers un pointeur comme premier argument, puis déréférencer. Comme ceci:

template<typename _T1, typename _T2>
    inline void
    _Construct(_T1** __p, const _T2& __value)
    {

       ::new(static_cast<void*>(*__p)) _T1(__value);
    }

En variante, une référence à un pointeur:

template<typename _T1, typename _T2>
    inline void
    _Construct(_T1*& __p, const _T2& __value)
    {

       ::new(static_cast<void*>(__p)) _T1(__value);
    }

Le débogueur doit vous laisser aller la pile d'appel. De cette façon, vous devriez être en mesure de voir la place dans votre propre code qui est à l'origine du défaut seg.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top