Memory leak



  • Wie wäre es denn besser?
    Gibts in c++ ne bessere Möglichkeit?

    Ich hatte vorher:

    uint8 response[46];
    

    und dann den ganzen malloc/free Kram weggelassen, aber hatte auch das Speicherproblem und dachte das malloc würde das beheben... aber auch damit gings nich...

    grüße



  • cole-hawk schrieb:

    uint8 response[46];
    

    und dann den ganzen malloc/free Kram weggelassen, aber hatte auch das Speicherproblem und dachte das malloc würde das beheben... aber auch damit gings nich...

    Sehr viel besser. Was spricht dagegen?
    Dein Speicherproblem liegt höchstwahrscheinlich wo anders. Was für eine Meldung bekommst du? Wie stellst du das Speicherleck fest? Evtl. liegt es an der Endlosschleife.



  • Ok, schon mal gut zu wissen, dass es so besser ist...
    Allerdings behebt es das Problem noch nicht..

    Also das ganze soll die Pakete von einem Messgerät entgegen nehmen, welches 8000 solche 46Byte großen Pakete pro Sekunde sendet.
    Normalerweise kann die "Endlosschleife" auch abgebrochen werden, nur hab ichs hier der übersicht halber raus gelassen und while(1) geschrieben, also dadruch nicht verwirren lassen...

    Fehler bekomme ich folgenden:
    terminate called after throwing an instance of std::bad_alloc

    Den Fehler hatte ich schon häufiger, nur konnte ich ihn nich einordnen... gestern habe ich dann festgestellt, dass er immer auftritt, wenn diese Messung sehr lange läuft... nach ca 600 Sekunden trat er meistens auf...
    Also hab ich mir (unter Ubuntu) mit dem System Monitor mal den Verlauf der Speichernutzung angeschaut...
    Anfangs auf 4,5% (=365MiB) steigt die Kurve während der Nutzung auf ca. 45% an (=3,6GiB) und dann kommt der bad_alloc Fehler.
    Nur das ganze passiert nicht, wenn ich das recv() auskommentiere, also muss es doch daran liegen. Ich dache halt, wenn ich das so mach:

    uint8 response[46];

    ...wird ständig neuer Speicher belegt und nicht mehr freigegeben, deshalb wollt ich das mit malloc fixen, aber hat ja nicht geklappt...
    Also kann ja nur noch das recv() das Problem verursachen, aber ich seh nicht, was ich falsch gemacht haben könnte...

    Danke für Eure Hilfe!
    Grüße



  • Ja, dann zeig mal mehr Code.
    std::bad_alloc wird von new geworfen, wo ist also new benutzt?



  • cole-hawk schrieb:

    uint8 response[46];

    ...wird ständig neuer Speicher belegt und nicht mehr freigegeben, deshalb wollt ich das mit malloc fixen, aber hat ja nicht geklappt...

    Jein. Du musst die Variable vor der while-Schleife deklarieren!



  • Siassei schrieb:

    cole-hawk schrieb:

    uint8 response[46];

    ...wird ständig neuer Speicher belegt und nicht mehr freigegeben, deshalb wollt ich das mit malloc fixen, aber hat ja nicht geklappt...

    Jein. Du musst die Variable vor der while-Schleife deklarieren!

    Ist das wirklich so? Hätte ich auch nicht so gemacht da ich mir gedacht habe das die Lebensdauer der Variable ja nur für den Block gilt. Also das die nach jedem Durchlauf aus dem Scope läuft und es somit nicht zu so einer derben Speichernutzung kommen sollte.



  • Achso.. Klaro, das response habe ich vor der Schleife deklariert.

    Das mit dem "new" ist so ne Sache... ich habe gar kein new verwendet... Aber ich schau nochmal nach, vielleicht ist ja doch irgendwo eins drin...
    Mein Programm ist insgesamt ziemlich groß, aber zur Zeit habe ich zum Testen nur diese eine Funktion mit der Schleife laufen, wobei ich außer dem recv in der schleife alles auskommentiert habe. Wie gesagt, nehm ich das recv raus und setz da ein kurzes sleep ein, passiert nix.. Speichernutzung steigt nicht an und auch kein bad_alloc.

    Hab grad nochmal getestet... nach 620 Sekunden kam der bad_alloc. In der Zeit stieg die Speichernutzung von ca. 0.4GiB auf 3.4GiB. Also 3GiB in der Zeit. Das kommt mir jetzt allerdings etwas viel vor, da ich ja gesagt habe pro Sekunde werden 8000mal die 46Byte gelesen.. Das macht grade mal 0.21GiB...
    Liegt das Problem also doch woanders... warum funktioniert es dann aber, wenn ich das recv weglasse...

    Alles sehr komisch hier 🙂



  • Hier liegen die 46 Byte auf dem Stack und sollten kaum schaden.

    typedef unsigned char uint8;
    
    funktion(int socket)
    {
      uint8 response[46];
      int r;
    
      while( (r=recv(socket, response, sizeof response, 0))>0 )
        /*fwrite( response, r, 1, stdout )*/;
    
    }
    


  • theta schrieb:

    Ja, dann zeig mal mehr Code.
    std::bad_alloc wird von new geworfen, wo ist also new benutzt?



  • Was machst du eigentlich mit den Daten die du bekommst? Verwirfst du die oder wie?
    Oder werden die gespeichert? Ich denke mal nicht das nur der Code in der Schleife steht.



  • Verwendest du vielleicht STL Container?



  • Nein, ich verwende die Daten, hatte es nur alles rausgelassen, weil ich denke, dass da das Problem nicht liegt...

    int socket_LJ_B;
    
    void Thread::setValues(int s)
    {
    socket_LJ_B = s;
    }
    void Thread::run()
    {
    	stopped = false;
    	unsigned long counter_Value;
    	int backLog;
    	int k, packetCounter = 0;
    	int totalPackets = 0;        				
    	int pps, pps_fio;
    	uint8 response[46];
    
    	FILE* LJout_fid;
    
    	LJout_fid =fopen(QFilenameLJ.toAscii().data(),"w");
    
    	gettimeofday(&tv_lj,NULL);
    
    	// read response from UE9 until stop button was clicked and stopped  
               gets true	
    	while(!stopped)													
    	{
    		//Reading response from LJ UE9
    		recv(socket_LJ_B, response , 46 , 0);		
    
    		// Checking for errors and getting data out of each StreamData response
    		// =================================================================>>>
    		totalPackets++;
    
    		// checksum check	
    		if(errorCheck((uint8 *)response, 46) == -1)		
    			stopped = true;
    
    		// check command bytes
    		if( response[1] != (uint8)(0xF9) || response[2] != (uint8)(0x14) || response[3] != (uint8)(0xC0) )
    		{
    			stopped = true;
    		}
    
    		// give error code
    		if(response[11] != 0)		
    		{
    			stopped = true;
    		}
    
    		//packetcounter
    		if(packetCounter != (int)response[10])	
    		{
    			stopped = true;
    		}
    
    		backLog = response[45] & 0x7F;
    
    		//Checking MSB for Comm buffer overflow
    		if( (response[45] & 128) == 128)
    		{
    			stopped = true;
    		}
    
    		// now get data out of packet
    		// ====================================================================
    		for(k = 12; k < 43; k += 8)								// step 8 because 2x Counterchannels (each 16bit) und 2x digital in channels (each 16bit)
    		{
    			// verschiebt jeweils um 8 bit nach links und addiert MSW und LSW
    			counter_Value =  (unsigned long)response[k+0]; 
    			counter_Value += (unsigned long)response[k+1] * pow(2,8);
    			counter_Value += (unsigned long)response[k+2] * pow(2,16);
    			counter_Value += (unsigned long)response[k+3] * pow(2,24);
    
    			pps_fio = response[k+4] & 0x04;						// 0x04 => (0100) == FIO2
    
    			if (pps_fio == 4)	pps = 1;								// 4 because (0100) = 4
    			else			pps = 0;
    
    			fprintf(LJout_fid, "%d\t%lu\n", pps , counter_Value);
    
    		} // end for 
    
    		if(packetCounter >= 255) packetCounter = 0;
    		else				 packetCounter++;
    
    	} // end while (reading packets in a loop)
    
    	fclose(LJout_fid);
    }
    

    stopped wird außerdem noch true gesetzt, wenn ich in meinem prog. auf stop klicke, also nicht wundern 😉

    Ich glaub nicht, dass ich STL Container verwende ...



  • Ok... ich Depp...
    Ich war mir so sicher, dass es der einzige Thread mit Schleife ist, der aufgerufen wird, dabei hatte ich noch eine andere kleine Funktion übersehen, die auch noch im Hintergrund lief. Da hatte ich in ner while Schleife ziemliche viele Variablen deklariert... double, int, QString usw...
    Ich denke & hoffe, dass es daran lag... werds gleich mal testen und sag dann bescheid...

    Danke für Eure Mithilfe!



  • Ohne deinen Code genau studiert zu haben, aber warum verwendest du kein Tool zum Aufspüren von deinem MemoryLeak? z.B. Valgrind oder vergleichbares im VS Studio

    (unsigned long)response[k+3] * pow(2,24)
    

    Merkwürdiger Code. "response" ist doch bereits ein uint8. Warum keine Shift-Operation? pow() ist im Vergleich zu << sehr langsam. Etwa wie Ente gegen Porsche 😃



  • Danke für den Tipp mit Valgrind... Werd ich mir mal anschauen...

    Den Shift-Operator werd ich auch mal ausprobieren...
    Ist schon ne ganze Weile her, dass ich das geschrieben habe und war damals froh, dass es überhaupt funktioniert hat 😃

    Zu meinem Problem... Es scheint schon besser geworden zu sein, die Speicherbelegung steigt nicht mehr so schnell, wie zuvor... aber immer noch ein klein wenig... Da die Messung später mal mehrere Stunden laufen soll, darf ichs nicht riskieren, dass sowas nochmal vorkommt...
    Werd also Valgrind morgen mal testen...

    Danke 😉
    Grüße



  • Vielleicht noch eins

    pps_fio = response[k+4] & 0x04;
    if (pps_fio == 4)
        pps = 1;
    else
        pps = 0;
    

    In der if-Abfrage kannst du die 4 weglassen. Das ist nur eine zusätzliche Fehlerquelle.

    if (pps_fio)
    


  • Danke Siassei. Ich sollte dir mal meinen lompletten Code schicken, da findest du bestimmt noch einige solche Sinnlosigkeiten 😉

    Hab valgrind mal ausprobiert, werd aber nicht schlau daraus...

    Das gibt ja 1Mio sachen aus...

    z.B.:

    ==1474== HEAP SUMMARY:
    ==1474==     in use at exit: 61,501,801 bytes in 402,729 blocks
    ==1474==   total heap usage: 4,276,975 allocs, 3,874,246 frees, 4,334,135,123 bytes allocated
    
    ==1474== LEAK SUMMARY:
    ==1474==    definitely lost: 316,792 bytes in 4,293 blocks
    ==1474==    indirectly lost: 53,278,044 bytes in 346,043 blocks
    ==1474==      possibly lost: 7,257,326 bytes in 44,479 blocks
    ==1474==    still reachable: 649,639 bytes in 7,914 blocks
    ==1474==         suppressed: 0 bytes in 0 blocks
    

    und dazwischen ne mio ausgaben wie diese:

    ==1474== 5,083,556 (27,776 direct, 5,055,780 indirect) bytes in 217 blocks are definitely lost in loss record 11,337 of 11,340
    ==1474==    at 0x402569A: operator new(unsigned int) (vg_replace_malloc.c:255)
    ==1474==    by 0x52A1E5E: ??? (in /usr/lib/libQtSvg.so.4.6.2)
    ==1474==    by 0x52B28F6: ??? (in /usr/lib/libQtSvg.so.4.6.2)
    ==1474==    by 0x52B4377: ??? (in /usr/lib/libQtSvg.so.4.6.2)
    ==1474==    by 0x52B46BD: ??? (in /usr/lib/libQtSvg.so.4.6.2)
    ==1474==    by 0x52B4C7A: ??? (in /usr/lib/libQtSvg.so.4.6.2)
    ==1474==    by 0x52C630F: QSvgTinyDocument::load(QString const&) (in /usr/lib/libQtSvg.so.4.6.2)
    ==1474==    by 0x52C7609: QSvgRenderer::load(QString const&) (in /usr/lib/libQtSvg.so.4.6.2)
    ==1474==    by 0x403EF45: QLed::paintEvent(QPaintEvent*) (in /usr/lib/libqledplugin.so)
    ==1474==    by 0x420F6B5: QWidget::event(QEvent*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474==    by 0x41B14DB: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474==    by 0x41B80F8: QApplication::notify(QObject*, QEvent*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474== 
    ==1474== 6,476,276 (172,960 direct, 6,303,316 indirect) bytes in 1,880 blocks are definitely lost in loss record 11,338 of 11,340
    ==1474==    at 0x402569A: operator new(unsigned int) (vg_replace_malloc.c:255)
    ==1474==    by 0x52C7868: QSvgRenderer::QSvgRenderer(QObject*) (in /usr/lib/libQtSvg.so.4.6.2)
    ==1474==    by 0x403EDA5: QLed::paintEvent(QPaintEvent*) (in /usr/lib/libqledplugin.so)
    ==1474==    by 0x420F6B5: QWidget::event(QEvent*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474==    by 0x41B14DB: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474==    by 0x41B80F8: QApplication::notify(QObject*, QEvent*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474==    by 0x4C60A3A: QCoreApplication::notifyInternal(QObject*, QEvent*) (in /usr/lib/libQtCore.so.4.6.2)
    ==1474==    by 0x42189D5: QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474==    by 0x4219814: QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474==    by 0x421964D: QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474==    by 0x421964D: QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474==    by 0x421964D: QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) (in /usr/lib/libQtGui.so.4.6.2)
    ==1474==
    

    wobei die hier geposteten die letzten beiden sind, also die mit den meisten lost bytes..

    vielleicht hätte ich dazu sagen sollen, dass ich mit qt arbeite und eine gui dazu gebastelt habe, die da mitläuft...
    Ich dachte halt, die Funktion, die ich da anfangs gepostet habe wäre mein einziges Problem, aber scheinbar steckt doch mehr dahinter...

    Danke nochmal für eure hilfe...
    Vielleicht find ich das Problem ja irgendwann mal.. Sonst muss ich halt damit leben 😉



  • Siassei schrieb:

    ...
    Jein. Du musst die Variable vor der while-Schleife deklarieren!

    Und warum das?



  • cole-hawk schrieb:

    vielleicht hätte ich dazu sagen sollen, dass ich mit qt arbeite und eine gui dazu gebastelt habe, die da mitläuft...
    Ich dachte halt, die Funktion, die ich da anfangs gepostet habe wäre mein einziges Problem, aber scheinbar steckt doch mehr dahinter...

    Na, das wird ja immer schöner 🙂

    Ich lege dir die offizielle Doku nahe. Beim durchlesen lernst du was und findest deine Fehler auch. Erst beim Debuggen lernt man das, was wichtig ist.
    http://valgrind.org/docs/manual/quick-start.html#quick-start.interpret


Anmelden zum Antworten