[C++] Valgrind - Was sagt mir die Fehlermeldung?

G

Green Mamba

Gast
Hallo,

ich habe ein Problem in einem Projekt von mir, und bin auf Valgrind gestoßen. Das Tool war mir bislang schon recht hilfreich, aber einige Dinge versteh ich momentan überhaupt nicht. Ich bekomme Seitenweise folgende Meldungen:
Code:
==7162== Conditional jump or move depends on uninitialised value(s)
==7162==    at 0x1CE64257: (within /usr/lib/libGLcore.so.1.0.7174)
==7162==
==7162== Conditional jump or move depends on uninitialised value(s)
==7162==    at 0x1CEF23B1: (within /usr/lib/libGLcore.so.1.0.7174)
==7162==
==7162== Conditional jump or move depends on uninitialised value(s)
==7162==    at 0x1CEF24CF: (within /usr/lib/libGLcore.so.1.0.7174)
==7162==
==7162== Conditional jump or move depends on uninitialised value(s)
==7162==    at 0x1CE9CC74: (within /usr/lib/libGLcore.so.1.0.7174)
==7162==
==7162== Conditional jump or move depends on uninitialised value(s)
==7162==    at 0x1CE80583: (within /usr/lib/libGLcore.so.1.0.7174)
Das ist nicht unbedingt ein Problem, aber die Übersicht bei den Ausgaben leidet doch sehr darunter. :(

Dann zu meinem eigentlichen aktuellen Problem. Wie kann es sein, dass wenn ich eine im Header-File deklarierte integer-Variable im Construktor der Klasse mit 0 initialisiere, ich so eine Meldung von Valgrind bekomme?
Code:
==7162== Invalid write of size 4
==7162==    at 0x8073164: TetraRenderer::TetraRenderer(SLFFEAProblemDataTetra*) (TetraRenderer.cpp:30)
==7162==    by 0x80715C1: OfflineDeformDataAdvisorSLFFEA::genData(QString) (OfflineDeformDataAdvisorSLFFEA.cpp:49)
==7162==    by 0x80604AE: FlexGUI::pushButtonLoad_released() (FlexGUI.qt.cpp:63)
==7162==    by 0x805F9F7: FlexGUI::qt_invoke(int, QUObject*) (moc_FlexGUI.qt.cpp:88)
==7162==    by 0x1C06D0ED: QObject::activate_signal(QConnectionList*, QUObject*) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C06D895: QObject::activate_signal(int) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C3DF9D8: QAction::activated() (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C3DFA3B: QAction::qt_emit(int, QUObject*) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C06D120: QObject::activate_signal(QConnectionList*, QUObject*) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C06D895: QObject::activate_signal(int) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C3C502B: QButton::clicked() (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C1054C8: QButton::mouseReleaseEvent(QMouseEvent*) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==  Address 0x1E4488B8 is 4 bytes after a block of size 12 alloc'd
==7162==    at 0x1B903458: operator new(unsigned) (in /usr/lib/valgrind/vgpreload_memcheck.so)
==7162==    by 0x80715A9: OfflineDeformDataAdvisorSLFFEA::genData(QString) (OfflineDeformDataAdvisorSLFFEA.cpp:49)
==7162==    by 0x80604AE: FlexGUI::pushButtonLoad_released() (FlexGUI.qt.cpp:63)
==7162==    by 0x805F9F7: FlexGUI::qt_invoke(int, QUObject*) (moc_FlexGUI.qt.cpp:88)
==7162==    by 0x1C06D0ED: QObject::activate_signal(QConnectionList*, QUObject*) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C06D895: QObject::activate_signal(int) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C3DF9D8: QAction::activated() (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C3DFA3B: QAction::qt_emit(int, QUObject*) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C06D120: QObject::activate_signal(QConnectionList*, QUObject*) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C06D895: QObject::activate_signal(int) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C3C502B: QButton::clicked() (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
==7162==    by 0x1C1054C8: QButton::mouseReleaseEvent(QMouseEvent*) (in /usr/lib/qt3/lib/libqt-mt.so.3.3.3)
Hier das Headerfile:
Code:
class TetraRenderer
{
  public:
    //!Constructs a new Renderer with Data already set.
    TetraRenderer (SLFFEAProblemDataTetra* data);
    SoSeparator* getSceneGraph ();
    static void partSelected (void * userdata, SoPath * path);
    static void partDeselected (void * userdata, SoPath * path);

  private:
    void buildGeometry();
    void makeTetra (int i);
    SoSeparator* m_pRoot;
    SoSelection* m_pSelection;
    SLFFEAProblemDataTetra* m_pTetraGeometryData;
    vector < int >* m_pHandleList;
    int m_numHandleList;
    int m_activeHandle;
};

und der Konstruktor:
Code:
TetraRenderer::TetraRenderer (ProblemDataTetra* data)
{
  m_pTetraGeometryData=data;
  m_pRoot = new SoSeparator;
  m_pRoot->ref();
  m_pSelection=new SoSelection;
  m_pSelection->ref();
  m_pRoot->addChild(m_pSelection);
  m_pSelection->policy = SoSelection::TOGGLE;
  m_pSelection->addSelectionCallback ( partSelected, this );
  m_pSelection->addDeselectionCallback ( partDeselected, this );
[COLOR="Red"]  m_numHandleList=0;
  m_activeHandle=0;
  m_pHandleList = new vector < int >;[/COLOR]
  buildGeometry(); //for testing purposes only
}
Jede der rot markierten Zeilen ruft eine Meldung in der Art wie oben hervor. Wäre für jede Hilfe dankbar. :)

Viele Grüße,
Green Mamba
 
Die ersten Meldungen kommen vermutlich durch uninitialisierte Variablen. Wird wohl schwierig zu finden... am besten immer alles initialisieren.

Zum eigentlichen Problem:
1.) Initialisierungslisten benutzen ;)
2.) Kann es sein, dass das Objekt zu dem Zeitpunkt schon geschrottet ist?

Vielleichst solltest Du erstmal alle Variablen intialisieren - die Pointer mit 0 - und dann mit new Objekte anlegen etc.
Und dann nochmal schauen, welche Meldungen eigentlich kommen.

Code:
TetraRenderer::TetraRenderer (ProblemDataTetra* data)
: m_pRoot( 0), m_pSelection( 0), m_pTetraGeometryData( data),
  m_pHandleList( 0), m_numHandleList( 0), m_activeHandle( 0)
{
  m_pRoot = new SoSeparator;
  m_pRoot->ref();
  m_pSelection=new SoSelection;
  m_pSelection->ref();
  m_pRoot->addChild(m_pSelection);
  m_pSelection->policy = SoSelection::TOGGLE;
  m_pSelection->addSelectionCallback ( partSelected, this );
  m_pSelection->addDeselectionCallback ( partDeselected, this );
  buildGeometry(); //for testing purposes only
}

Warum legst Du den vector eigentlich dynamisch an?
 
Danke, das mit der Initialisierungs-Liste war mir neu. :)
Ich werde das jetzt erst mal durch alle 30 Klassen ziehen, und dann weiter schauen. Also sehe ich das richtig, dass bei einem sauberen Programm keine einzige Meldung von Valgrind kommen dürfte?

2.) Kann es sein, dass das Objekt zu dem Zeitpunkt schon geschrottet ist?
Tja, das frage ich mich ja auch. :D
Ich habe aber einen Verdacht. Bevor ich ein Objekt der Klasse TetraRenderer erzeuge hatte ich noch einige Debug-Zeilen. Wenn ich diese auskommentiere, bekomme ich die Meldung Nr. 2 aus obigem Post nicht mehr. :rolleyes:
Danke erst mal für die Hilfe! :)
 
Naja, keine einzige Meldung... sagen wir mal so, Valgrind macht bestimmt auch nicht alles richtig :)

Womit fast jedes Tool Schwierigkeiten hat ist new und delete. Da bekommt man immer mal wieder sowas wie "mismatched delete/free", weil er der Meinung ist, man hätte delete[] auf einen Zeiger von new benutzt und umgekehrt.
STLport kann das z.B. umgehen, indem es new und delete einfach auf malloc/free abbildet, was die meisten Tools raffen.

Fehler wie invalid write sollte man aber immer ernst nehmen.
 
Zuletzt bearbeitet:
So, ich hab die initialisierung mal überall gemacht, aber ich bekomme schätzungsweise immernoch genauso viele Meldungen. :p
Aber immerhin hab ich jetzt ein besseres Gefühl, und ein bisschen mehr übersicht im Code. :D

Ok, soweit ich das überblicken kann lag die obere Meldung tatsächlich an den paar Zeilen debug-Code. Hab ihn rausgenommen, und jetzt läufts.

PS: Zur Info, die Zeilen waren:
Code:
  //ProgramManager *p = ProgramManager::getProgramManager();
cout << filename << endl;
*m_pFileName = filename;
cout << filename << endl;
 ...
const int* elements=geometry->getElementsPointer ();
const float* nodes=geometry->getNodesPointer ();
Keine Ahnung was da los war. :confused_alt:
Ich tippe aber mal auf "*m_pFileName = filename;"
Damit habe ich wohl auf das Ziel eines nicht initialisierten Zeigers geschrieben. Vielleicht hab ich damit auch andere Funktionspointer überschrieben, oder den Stack zerbröselt. :rolleyes:
 
Auf jeden Fall, aber meines wissens die performanteste Methode bei Echtzeitanwendungen wo es auf jeden Frame ankommt. :)
 
Zurück
Oben