WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Verhinderung von Memory Leaks mit selbstverfassten Mex Files

 

Scriptor
Forum-Century

Forum-Century


Beiträge: 217
Anmeldedatum: 22.02.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 26.11.2010, 00:52     Titel: Verhinderung von Memory Leaks mit selbstverfassten Mex Files
  Antworten mit Zitat      
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.

Mit den besten Grüßen,

Icke
Private Nachricht senden Benutzer-Profile anzeigen


Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 26.11.2010, 02:42     Titel: Re: Verhinderung von Memory Leaks mit selbstverfassten Mex F
  Antworten mit Zitat      
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
Private Nachricht senden Benutzer-Profile anzeigen
 
Scriptor-Gast

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 26.11.2010, 03:50     Titel: Re: Verhinderung von Memory Leaks mit selbstverfassten Mex F
  Antworten mit Zitat      
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.

Vielen Dank nochmal,

Scriptor
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 26.11.2010, 04:09     Titel: Re: Verhinderung von Memory Leaks mit selbstverfassten Mex F
  Antworten mit Zitat      
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:
Code:
A = rand(1000, 1000);
B = A;

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.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Scriptor
Themenstarter

Forum-Century

Forum-Century


Beiträge: 217
Anmeldedatum: 22.02.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.11.2010, 00:41     Titel:
  Antworten mit Zitat      
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?

Gleiches gilt für plhs, welches man mit

mxCreateDoubleMatrix

entsprechend allociert.

Code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <complex.h>
#include "nfft3util.h"
#include "nfft3.h"
#include "matrix.h"
#include "mex.h"  


#define test printf("\n\ntest\n\n");
#define line printf("\n");

#define stop mexErrMsgTxt("\n\nStop\n\n");
         
         
double complex* infft(int d, int M, int N[], double *pos, double complex *in, int iter, double *residual_error, double *w, char *modus, char *method, char *process)
{
  nfft_plan p;                      
  solver_plan_complex ip;
  int n[d];
  int h, Mf = 1;
  for(h = 0; h < d; h++)
  {
    Mf = Mf*N[h];
    n[h] = 2*N[h];
  }
 
  /** init a two dimensional plan*/
  nfft_init(&p, d, N, M);
.....
  double complex *out  = malloc(sizeof(double complex)*Mf);
 
.....
   return out;

  free(out); free(in); free(pos); free(modus); free(method); free(process); free(n); free(N); free(w)
  solver_finalize_complex(&ip);
  nfft_finalize(&p);
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
 
  double *i1      = mxGetPr(prhs[0]);
  double *i2      = mxGetPr(prhs[1]);
  double *pos     = mxGetPr(prhs[2]);
  double *cr      = mxGetPr(prhs[3]);
  double *d_iter  = mxGetPr(prhs[4]);
  double *window  = mxGetPr(prhs[5]);
 
  char   *modus   = mxArrayToString(prhs[6]);
  char   *method  = mxArrayToString(prhs[7]);
  char   *process = mxArrayToString(prhs[8]);
 
  int iter  = (int)d_iter[0];
  int mc    = mxGetM(prhs[3]);
  int nc    = mxGetN(prhs[3]);
  int nmc   = mc*nc, h;

  int d = mxGetN(prhs[1]);
  int Mf = 1;

  int N[d];
 
 
  for( h = 0; h < d; h++)
  {
    N[h]  = (int)i2[h];
    Mf = Mf*N[h];
  }

  int M = (int)i1[0];

  double complex *in = malloc(sizeof(double complex)*nmc);

  if(mxIsComplex(prhs[3]))
  {
    double *ci = mxGetPi(prhs[3]);
    for( h = 0; h < nmc; h++)  
       in[h] = cr[h] + I*ci[h];  
  }
  else
    for( h = 0; h < nmc; h++)
      in[h] = cr[h] + I*0;
   
  double *res = malloc(sizeof(double)*(iter + 1));
 
  double t;
  if(~strcmp(modus,"time_measurement") || ~strcmp(modus,"residuals+time"));
      t = nfft_second();
     
  double complex *out = infft( d, M, N, pos, in, iter, res, window, modus, method, process);

  if(~strcmp(modus,"residuals+time"))
  {
       t = nfft_second() - t;
       nlhs = 3;
  }
  else if(~strcmp(modus,"time_measurement"))
  {
      t = nfft_second() - t;
      nlhs = 2;
  }
  else
      nlhs = 1;
 
  if(d==1)
    plhs[0] = mxCreateDoubleMatrix(1, Mf, mxCOMPLEX);
  else
    plhs[0] = mxCreateNumericArray(d, N, mxDOUBLE_CLASS, mxCOMPLEX);
     
  /**return output var*/
  double *o1r = mxGetPr(plhs[0]);/**taking ptr for real part of output var*/
  double *o1i = mxGetPi(plhs[0]);/**taking ptr for imag part of output var*/
 
  for ( h = 0; h < Mf; h++) /**interface-ptr show on output data*/
  {
    o1r[h] = creal(out[h]);
    o1i[h] = cimag(out[h]);
  }
 
  if((strcmp(modus,"time_measurement") == 0) | (strcmp(modus,"residuals+time") == 0))
  {
    plhs[1] = mxCreateDoubleMatrix(1,1,mxREAL);
    double *o2t = mxGetPr(plhs[1]);
    o2t[0] = t;
  }
 
  if(strcmp(modus,"residuals+time") == 0)
  {
    plhs[2] = mxCreateDoubleMatrix(1, (iter+1), mxREAL);
    double *o3r = mxGetPr(plhs[2]);
    for( h = 0; h < (iter+1); h++)
        o3r[h] = res[h];
  }
 
  free(in); free(res); free(out);
}


Ich weiß dann aber auch nicht mehr so ganz weiter. Ich denke eigentlich keinen Fehler im normalen C gemacht zu haben aber es scheint echt so.

Vielen Dank für dein Interesse und Hilfe,

Scriptor
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 30.11.2010, 23:37     Titel:
  Antworten mit Zitat      
Hallo Scriptor,

Code:

...
double complex* infft(int d, int M, int N[], double *pos, double complex *in, int iter, double *residual_error, double *w, char *modus, char *method, char *process)
{
   ...
   return out;

  free(out); free(in); free(pos); free(modus); free(method); free(process); free(n); free(N); free(w)
  solver_finalize_complex(&ip);
  nfft_finalize(&p);
}
...

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.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Scriptor
Themenstarter

Forum-Century

Forum-Century


Beiträge: 217
Anmeldedatum: 22.02.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 06.12.2010, 21:10     Titel:
  Antworten mit Zitat      
Hallo Jan,

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?

Mfg Ich
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 06.12.2010, 22:25     Titel:
  Antworten mit Zitat      
Hallo Scriptor

Zitat:
Das Modus und der andere Klimbims sind über die mxFunktionen aus prhs extrahiert. Daher denke ich nicht, dass dieses freigegeben werden muss oder?


Du hast "modus" so erzeugt:
Code:
modus   = mxArrayToString(prhs[6])

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
Private Nachricht senden Benutzer-Profile anzeigen
 
Scriptor
Themenstarter

Forum-Century

Forum-Century


Beiträge: 217
Anmeldedatum: 22.02.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 15.12.2010, 11:44     Titel:
  Antworten mit Zitat      
[quote="Jan S"]Hallo Scriptor

[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?

Mfg Ich
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 16.12.2010, 05:07     Titel:
  Antworten mit Zitat      
Hallo Scriptor,

Zitat:
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
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

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
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

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.