Verfasst am: 26.11.2010, 00:52
Titel: Verhinderung von Memory Leaks mit selbstverfassten Mex Files
Servus Leute,
Ich nutze selbstgehauene Mex Files für Typ 3 non uniform fast Fourier Transform Funktionen. Meine Frage ist aber mehr Mex Basics Natur.
Ich habe eine Mexfunktion mit 10 Eingabevariablen. Die rufe
ich mit z.B.
double * arg1 = mxGetPr(prhs[0]);
ab oder char etc pp. Is ja Banane. Ergebnis und so alles fein und gut aber es entstehen Memory Leaks, d.h. der belegte RAM Speicherausnutzung steigt obwohl der Work Space Speicher nur mit einem kleinen Anteil RAM belegt und er fällt erst wieder auf Normalniveau, wenn ich Matlab ausschalte.
Daher Diagnose meinerseits irgendwo ein Memory Leak (oder auch mehrere) in einer der Mex Files.
Ich nutze dabei gcc 4..... irgendwas und linke die Standart libs wie string.h, complex.h etc mit hinzu, sodass ich standart c99 Befehle nutzen kann z.B. malloc, free....
Diesewie oben erzugten double und Complex Pointer werden anschließend in eine Unterfunktion übergegeben. Diese Funktion löscht aber erzeugte und übergegebene Variablen am Ende wieder, heißt er gibt den Speicher frei, auch die der zurückgegebenen Variablen. Die tue ich auch mit erzeugten Pointern mit malloc. Wenn ich allerdings einen erzeugten Pointer aus prhs mit free freigebe, hängt sich Matlab bei der Ausnutzung auf.
Was muss ich bei der Speicherfreigabe beachten, dass die Memoryleaks nicht mehr auftreten? Ich gehe davon aus, dass die Leaks von prhs oder den daraus extrahierten pointern stammen, die ich im Anschluss NICHT freigebe.
muss ich für plhs Pointer auch freigeben?welche ich mit mxGetPr freigebe? ich geh doch mal aus nicht oder?
Über einen Tipp zum Speicherhandling wäre ich sehr froh. Die Matlab Page beantwortetmir die Frage nicht ganz einwandfrei. Vll habe ich die Pointerei immer noch nicht bis zum Schluss kapiert.
Verfasst am: 26.11.2010, 02:42
Titel: Re: Verhinderung von Memory Leaks mit selbstverfassten Mex F
Hallo Scriptor,
Zitat:
Was muss ich bei der Speicherfreigabe beachten, dass die Memoryleaks nicht mehr auftreten?
Die Antwort ist trivial:
Jeder Speicher, der per MALLOC allociert wurde, muss mit FREE wieder freigegeben werden, bevor die Funktion wieder zu Matlab zurückkehrt.
Speicher, der mit mxMalloc allociert wurde, wird von Matlab automatisch freigegeben, falls er nicht zu einem der Rückgabe-Werte gehört. Es ist zwar ein unsauberer Programmierstil, sich auf diese Automatik zu verlassen. Manchmal ist es aber der beste Ausweg, z.B.:
Code:
double *x;
x = (double *) mxMalloc(1000 *sizeof(double));
status = AnyFunction();
if(status == 0){
mexErrMsgIdAndTxt("My:Bad:Program", "Failed");
}
mxFree(x);
In diesem Fall kümmert sich Matlab darum x wieder freizugeben, falls das Programm von einem Fehler in AnyFunction() gestoppt wird.
Insofern ist mxMalloc ein echtes Highlight, wenn man sich mit Memoryleaks herumschlägt.
Eine genauere Auskunft ist nur möglich, wenn Du die relevanten Abschnitte aus Deinem Code postest.
Gruß, Jan
Scriptor-Gast
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 26.11.2010, 03:50
Titel: Re: Verhinderung von Memory Leaks mit selbstverfassten Mex F
Jan S hat Folgendes geschrieben:
Hallo Scriptor,
Die Antwort ist trivial:
Jeder Speicher, der per MALLOC allociert wurde, muss mit FREE wieder freigegeben werden, bevor die Funktion wieder zu Matlab zurückkehrt.
is klar
Zitat:
Speicher, der mit mxMalloc allociert wurde, wird von Matlab automatisch freigegeben, falls er nicht zu einem der Rückgabe-Werte gehört. Es ist zwar ein unsauberer Programmierstil, sich auf diese Automatik zu verlassen.
...
Insofern ist mxMalloc ein echtes Highlight, wenn man sich mit Memoryleaks herumschlägt.
Eine genauere Auskunft ist nur möglich, wenn Du die relevanten Abschnitte aus Deinem Code postest.
Gruß, Jan
Hallo Jan,
Danke für deine Antwort zu so später Stunde.
Die Frage kann ich nochmal kurz fassen, dazu muss ich keinen Code zurecht schnippseln.
Du sagst, dass die Datentypen wie mxArrays von sich aus gelöscht werden ist das richtig?
Wenn dem so ist, muss man sich über diesen Speicher eigentlich keine Sorgen machen. Wie verhält es sich mit Pointern, die man mit der Funktion
mxGetPr
von den mxArrays(wie prhs) ableitet? Wie wird der Speicher dort freigegeben?
Wenn ich das mit free() durchführe, hängt sich der Ablauf auf.
Bsp
double *arg1 = mxGetPr(prhs[0]);
free(arg1); --> dit klappt nich,
Da vermute ich mein Leak, da ich eigentlich immer hinter mir aufräume, aber die mex Datenstrukturen aber nicht so kenne.
Verfasst am: 26.11.2010, 04:09
Titel: Re: Verhinderung von Memory Leaks mit selbstverfassten Mex F
Hallo Scriptor,
Zitat:
Du sagst, dass die Datentypen wie mxArrays von sich aus gelöscht werden ist das richtig?
Speicher, der mit mxMalloc alloziert wurde, wird beim Rücksprung nach Matlab automatisch freigegeben. Dazu gehören z.B. auch die Daten der mxArray Variablen.
Zitat:
Wenn dem so ist, muss man sich über diesen Speicher eigentlich keine Sorgen machen.
Solange man nach Matlab zurück springt, muss man sich keine Sorgen machen. Wenn man das Mex-File aber in einem Stand-Alone-Programm verwendet, springt man nicht nach Matlab zurück! Ein suaberer Programmierstil ist also auf alle Fälle die sicherste Methode.
Zitat:
double *arg1 = mxGetPr(prhs[0]);
free(arg1); --> dit klappt nich,
Mit kräuseln sich die Fussnägel!
Die Daten-Arrays der Input-Argumente sollten auf keinen Fall, niemals, bestimmt nicht freigegeben werden! Und da sie mit mxMalloc alloziert wurden, wird es auf jeden Fall crashen, wenn Du versuchst sie mit "free()" frei zu geben!
Wenn man mutig ist und sich mit den Matlab-internen Datenstrukturen extrem gut auskennt, kann man die Daten-Arrays mit mxFree freigeben. Davor muss man aber testen, ob die Daten wirklich nur zu dieser einen Variablen gehören - und dafür gibt es nicht mal einen dokumentierten Befehl! Variablen können sich den Speicher nämlich auch teilen:
Wenn Du jetzt A als Input für Dein Mex-File verwendest und das Daten-Array mit "mxFree(mxGetPr(prhs[0]))" frei gibst, hat B keine validen Daten mehr (A natürlich auch nicht mehr)!
Pointer auf Daten-Arrays musst Du aber zum Glück sowieso nicht freigeben, da Du dafür ja auch keinen Speicher alloziert hast!
Sehr zu empfehlen ist eine konservative Methode zur Verwendung von Malloc und Free: Versuche sie wie eine Schleife zu programmieren, indem Du immer, wenn Du "mxMalloc" (oder "malloc") schreibst, gleich danach den entsprechenden "mxFree" (oder "free")-Befehl darunter schreibst. Alles zusätzliche wird dann zwischen diesen beiden Zeilen eingefügt. Allozieren und Freigeben erfolgt dann immer in der gleichen Funktion und auf dem gleichen Level, z.B. in verschiedenen IF oder FOR-Blöcken. Wenn sich das nicht vermeiden läßt, schreibe das explizit in einen Kommentar und überlege dreimal, ob Du keinen Designfehler gemacht hast.
wenn man davon ausgehen kann, dass Matlab die mxArrays prhs usw von Matlab ohne eigenes Zutun korrekt verwaltet werden, hieße dass ja, dass man aus ihnen extrahierte Pointer nicht mehr bearbeiten muss, sehe ich das richtig?
Die ganzen FREE's und finalize-Funktionen werden nicht aufgerufen, weil das Unterprogramm vorher per RETURN zum Caller zurückspringt. Das sollte ein Memory-Leak bedeuten.
"free(out)" wäre hier fatal!
Ich würde "modus" etc auf jeden Fall in der Hauptfunktion mit "free" freigeben, weil sie auch dort per "malloc" reserviert wurden.
etwas spät melde ich mich um mich zu bei dir zu bedanken. Daran lag es wirklich. Nun funktioniert alles so, wie es soll. Das Modus und der andere Klimbims sind über die mxFunktionen aus prhs extrahiert. Daher denke ich nicht, dass dieses freigegeben werden muss oder?
Gemäß der Dokumentation muss der Speicher, der dabei allociert wird, mit mxFree wieder freigegeben werden. Allerdings schafft Matlab das auch automatisch beim Rücksprung aus dem Mex-File. Ich würde es aber dennoch eine ordentliche Speicherverwaltung empfehlen.
[quote]Das Modus und der andere Klimbims sind über die mxFunktionen aus prhs extrahiert. Daher denke ich nicht, dass dieses freigegeben werden muss oder?[/quote]
Du hast "modus" so erzeugt:
[code]modus = mxArrayToString(prhs[6])[/code]
Gemäß der Dokumentation muss der Speicher, der dabei allociert wird, mit mxFree wieder freigegeben werden. Allerdings schafft Matlab das auch automatisch beim Rücksprung aus dem Mex-File. Ich würde es aber dennoch eine ordentliche Speicherverwaltung empfehlen.
Gruß, Jan[/quote]
Habe ich probiert und er ist abgeschmiert. Das macht auch Sinn, denn diesen Matlab String benutze ich später wieder. Wenn der Speicherbereich wieder freigegeben ist, schmiert mir der Kollege dann ab wenn nix da is was eigentlich soll.
Btw gibt es die Möglichkeit ein double complexes Datenfeld zu aus prhs[irgendwas] zu extrahieren oder get das nur über die Real und Imaginärpointer? Ich habe gesucht und gesucht.
BTW gibt es die Datenstruktur von mxArrays irgendwo nachzulesen?
Btw gibt es die Möglichkeit ein double complexes Datenfeld zu aus prhs[irgendwas] zu extrahieren oder get das nur über die Real und Imaginärpointer?
Du bekommst die komplexen Werte mit mxGetPi() und die Real-Teile mit mxGetPr(). Eine andere Methode wäre nicht sinnvoll.
Zitat:
gibt es die Datenstruktur von mxArrays irgendwo nachzulesen?
Nun, eigentlich nicht. Aber Matlab liefert ja die Header-Dateien mit aus. Vorallem der Teil, der sich mit inlined-mxArrays befasst enthält eine Menge nicht-dokumentierter Details.
James Tursa hat in der FEX Files veröffentlicht, die auf diese Details zugreifen. Die genaue Implentierung wechselt aber öfter mal mit den Matlab Versionen.
Gruß, Jan
Einstellungen und Berechtigungen
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum posten Du kannst Dateien in diesem Forum herunterladen
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.