(Note à l'intention des futurs lecteurs: L'erreur, sans surprise, est dans mon code et non std :: _ Rb_tree_rebalance_for_erase())Segmentation fault en fonction std std :: _ Rb_tree_rebalance_for_erase()
Je suis un peu nouveau à la programmation et je ne sais pas comment gérer une erreur de segmentation qui semble provenir d'une fonction std. J'espère que je fais quelque chose de stupide (c'est-à-dire, abuser d'un conteneur), parce que je n'ai aucune idée de comment le réparer.
L'erreur précise est
Programme signal reçu EXC_BAD_ACCESS, n'a pas pu accéder à la mémoire.
Raison: KERN_INVALID_ADDRESS à l'adresse: 0x000000000000000c
0x00007fff8062b144 dans std :: _ Rb_tree_rebalance_for_erase()
(gdb) backtrace
# 0 0x00007fff8062b144 dans std :: _ Rb_tree_rebalance_for_erase()
# 1 0x000000010000e593 dans la simulation de runEpidSim (ce = 0x7fff5fbfcb20) à stl_tree.h: 1263
# 2 0x0000000100016078 en main() à main.cpp: 43
la fonction qui sort juste avec succès avant que le défaut de segmentation met à jour le contenu de deux conteneurs. L'un est un boost::unordered_multimap
appelé carriage
; il contient un ou plusieurs objets struct Infection
. L'autre conteneur est de type std::multiset< Event, std::less< Event > > EventPQ
appelé ce
.
void Host::recover(int s, double recoverTime, EventPQ & ce) {
// Clearing all serotypes in carriage
// and their associated recovery events in ce
// and then updating susceptibility to each serotype
double oldRecTime;
int z;
for (InfectionMap::iterator itr = carriage.begin(); itr != carriage.end(); itr++) {
z = itr->first;
oldRecTime = (itr->second).recT;
EventPQ::iterator epqItr = ce.find(Event(oldRecTime));
assert(epqItr != ce.end());
ce.erase(epqItr);
immune[ z ]++;
}
carriage.clear();
calcSusc(); // a function that edits an array
cout << "Done with sync_recovery event." << endl;
}
La dernière ligne cout <<
apparaît immédiatement avant la faute de SEG.
Mon idée à ce jour est que le rééquilibrage est tentée sur ce
immédiatement après cette fonction, mais je ne suis pas sûr pourquoi le rééquilibrage manquerait.
Mise à jour
J'ai confirmé la faute de seg en va (bien que le programme se bloque alors immédiatement pour d'autres raisons) lorsque je retire ce.erase(epqItr);
. Je suis capable de supprimer des événements avec succès dans un autre endroit du code; le code que j'utilise là pour effacer des éléments dans ce
est identique à ce qui est ici.
sanstracé rétrograde optimisation (grâce, BDK) révèle beaucoup plus d'informations:
Programmesignal reçu EXC_BAD_ACCESS, n'a pas pu accéder à la mémoire.
Raison: KERN_INVALID_ADDRESS à l'adresse: 0x000000000000000c
0x00007fff8062b144 dans std :: _ Rb_tree_rebalance_for_erase()
(gdb) backtrace
# 0 0x00007fff8062b144 dans std :: _ Rb_tree_rebalance_for_erase()
# 1 0x00000001000053d2 dans std :: _ Rb_tree, std: : moins,> std :: allocator> :: efface (this = 0x7fff5fbfdfe8, __position = {_ M_node = 0x10107cb50}) à> stl_tree.h: 1263
# 2 0x0000000100005417 dans std :: multiset, std :: allocator> :: effacer (this = 0x7fff5fbfdfe8, __position = {_ M_node = 0x10107cb50}) à stl_multiset.h: 346 # 3 0x000000010000ba71 dans la simulation de runEpidSim (ce = 0x7fff5fbfcb40) à Simulation.cpp: 426
# 4 0x000000010001fb31 en main() à main.cpp: 43
À moins Xcode est en train de lire les numéros de ligne mal, le seul stl_tree.h dans mon disque dur est vide sur la ligne 1263.
quelques personnes ont demandé à voir la fonction qui appelle récupérer. Il est un peu compliqué:
struct updateRecovery{
updateRecovery(int s, double t, EventPQ & ce) : s_(s), t_(t), ce_(ce) {}
void operator() (boost::shared_ptr<Host> ptr) {
ptr->recover(s_, t_, ce_);
}
private:
int s_;
double t_;
EventPQ & ce_;
};
// allHosts is a boost::multiindex container of boost::shared_ptr<Host>
// currentEvents is the EventPQ container
// it is an iterator to a specific member of allHosts
allHosts.modify(it, updateRecovery(s, t, currentEvents));
cout << "done with recovery" << endl;
Les dernières cout
impressions. Le code a travaillé auparavant sans cette version particulière de la fonction de récupération.
Noah Roberts a à juste titre que le problème est à Simulation.cpp, ligne 426. saut ci-dessous pour une solution embarrassante.
Qu'y a-t-il à stl_tree.h: 1263? –
Le seul fichier stl_tree.h qui apparaît sur mon disque dur (également le seul fichier contenant '_Rb_tree_rebalance_for_erase' sur ma HD) est * vide * sur la ligne 1263 (?!). J'utilise gcc 4.2.1 (Apple build 5646) sur i686-apple-darwin10. La fonction rebalance_for_erase est définie sur les lignes 299-429. – Sarah
Si vous mettez un cout dans le code appelant juste après l'appel de Host :: recover, cela s'imprime-t-il? En outre, essayez de compiler avec toutes les optimisations et inlining désactivées et vous pouvez obtenir une trace de pile plus utile – bdk