Forum: Mikrocontroller und Digitale Elektronik MemleakErrormeldung


von Memleak (Gast)


Lesenswert?

Hallo,

ich habe eine Funktion, die bekommt einen Pointer auf einen 
Speicherbereich übergeben, in welchem sich eigentlich nur ein String 
befindet.
Innerhalb der Funktion erzeuge ich nun einen neuen Pointer, der beim 
Beginn der ursprünglichen Pointeradresse ansetzt.
1
void function(char* buf)
2
{
3
4
//... ein paar Aktionen
5
6
char* RecPointer = (char*) malloc(sizeof(char) * strlen(buf));
7
RecPointer = buf;
8
9
/*... ein paar Aktionen mit dem RecPointer, Auslesen und Setzen betimmter Bytes im Datenstrom...*/
10
11
//anschließend:
12
free(RecPointer);
13
}


Nun ist das Problem:
ich erhalte Errormeldungen vom Typ Memleak.
Warum ist das so, wie kann ich diese umgehen, was hätte ich hier anders 
machen müssen?

von nicht"Gast" (Gast)


Lesenswert?

Du weist deinem pointer eine neue Adresse zu. Du wirst deinen buffer mit 
strncpy kopieren müssen.

von Memleak (Gast)


Lesenswert?

Ich dachte ich erzeuge erstmal nur einen Pointer, der auf die gleiche 
Adresse von Buf zeigt... und ggf. kleiner ist, weil ich nur die strlen 
von buf haben will... oder nicht?

von Einer K. (Gast)


Lesenswert?

> char* RecPointer =
Dein Pointer ist eine stinknormale lokale Variable.

> free(RecPointer)
Diese lokale Variable musst/darfst/kannst du nicht freigeben!
Das passiert automatisch.
Der vorher definierte Pointer verfällt beim verlassen der Funktion.


Wenn du auch den Speicherbereich freigeben willst, auf den der Pointer 
zeigt, dann....
Aber das sehe ich hier nicht.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Memleak schrieb:
> Ich dachte ich erzeuge erstmal nur einen Pointer

malloc "erzeugt" keine Pointer. malloc fordert dynamischen Speicher an, 
und gibt als Ergebnis einen Pointer zurück, der darauf zeigt.

Wenn Du den Pointer wegwirfst (was Du mit Deiner Zuweisung unweigerlich 
machst), geht der per malloc angeforderte Speicher verloren. Du kannst 
nicht mehr darauf zugreifen, und Du kannst ihn auch nicht mehr 
freigeben.

von Memleak (Gast)


Lesenswert?

hmmm... ok, dann nur einen Pointer in der Funktion erzeugen, auf den 
übergebenen Speicherbereich zeigen lassen, damit arbeiten und am Ende 
der Funktion vergessen, hat mir schonmal sehr geholfen, Danke!


Habe noch eine weitere Frage, und zwar ein ähnlich gelagertes Problem, 
genutzt wird die Funktion realloc.
1
BufPtr = realloc(BufPtr, LENGTH);

hier erhalte ich Errormeldung: memleakOnRealloc,


Der Speicher kann und soll allerdings tatsächlich wachsen und auch 
schrumpfen können und die Errormeldung betrifft genau diejenigen Zeilen, 
die im Falle des Schrumpfens aufgerufen werden.
Bin mir daher nicht sicher, ob es wirklich ein Fehler ist, oder nur eine 
zu scharf eingestellte Warnung, die einen Error erzeugt, aber auch für 
diesen Fall würde ich dennoch gerne wissen, wie ich "Errorfrei" aus der 
Situation herauskomme...

von Peter II (Gast)


Lesenswert?

Arduino F. schrieb:
>> free(RecPointer)
> Diese lokale Variable musst/darfst/kannst du nicht freigeben!
> Das passiert automatisch.

Unsinn. Jeder Pointer muss man freigeben. Zu jedem malloc gehört ein 
free.

von Nop (Gast)


Lesenswert?

Memleak schrieb:

> Bin mir daher nicht sicher, ob es wirklich ein Fehler ist

Ist es, denn wenn das Realloc scheitert, kriegst Du zwar einen 
Nullpointer zurück, aber damit überschreibst Du den alten Bufferzeiger, 
und wie willst Du den Buffer dann jemals wieder freigeben?

Daher macht man das besser nach dem Muster:
1
BUF_T *TmpBufPtr = realloc(BufPtr, LENGTH);
2
if (TmpBufPtr == NULL)
3
{
4
    // error handling
5
    // BufPtr STILL points to allocated memory but can be free'd
6
} else
7
{
8
    BufPtr = TmpBufPtr ;
9
    // more stuff
10
}

von Adele (Gast)


Lesenswert?

Peter II schrieb:
> Arduino F. schrieb:
>>> free(RecPointer)
>> Diese lokale Variable musst/darfst/kannst du nicht freigeben!
>> Das passiert automatisch.
>
> Unsinn. Jeder Pointer muss man freigeben. Zu jedem malloc gehört ein
> free.

Und warum kommt dann beim TO der Fehler?
Was hat er falsch gemacht und wie kann er es besser machen?

von Peter II (Gast)


Lesenswert?

Adele schrieb:
> Und warum kommt dann beim TO der Fehler?
> Was hat er falsch gemacht und wie kann er es besser machen?

er überschreibt seinen Pointer, damit gibt er beim free den falschen 
Speicher frei.
1
char* RecPointer = (char*) malloc(sizeof(char) * strlen(buf));

so jetzt überschreibt er den Zeiger, wo er sich Speicher besorgt hat.
1
RecPointer = buf;

damit war das malloc sinnlos. Das Free gibt dann den Speicher von buf 
was so bestimmt nicht gewollt ist.

von Peter II (Gast)


Lesenswert?

Nachtrag:

den Speicher den er mit malloc kann er gar nicht mehr freigeben, weil er 
seinen Pointer überschrieben hat. Damit hat er ein Memleak

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Nop schrieb:
> Ist es, denn wenn das Realloc scheitert, kriegst Du zwar einen
> Nullpointer zurück, aber damit überschreibst Du den alten Bufferzeiger,

Ja.

Peter II schrieb:
> er überschreibt seinen Pointer, damit gibt er beim free den falschen
> Speicher frei.[...]

Das liest sich so, als ob ich nach einem p1 = malloc(l1) und 
anschließendem erfolgreichen p2 = realloc(p1, l2) später auch noch p1 
freigeben müsste. Dem ist nicht so. Ich muss nur den zuletzt erhaltenen 
Pointer freigeben, also p2.

von Peter II (Gast)


Lesenswert?

Frank M. schrieb:
> Das liest sich so, als ob ich nach einem p1 = malloc(l1) und
> anschließendem erfolgreichen p2 = realloc(p1, l2) später auch noch p1
> freigeben müsste. Dem ist nicht so. Ich muss nur den zuletzt erhaltenen
> Pointer freigeben, also p2.

ich habe mich auf den 1. Code bezogen, da gab es kein realloc.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Memleak schrieb:
> BufPtr = realloc(BufPtr, LENGTH);

Du solltest niemals das Ergebnis von realloc direkt an den übergebenen 
Pointer zuweisen.

Wie signalisiert realloc, daß es keinen freien Speicher mehr gibt?

Indem es NULL zurückgibt.

Was passiert dann mit dem Pointer, der auf den bislang verwendeten 
Speicher zeigt?

Er wird mit NULL überschrieben.

Und ... wie kommt man jetzt an den bislang verwendeten Speicher 'ran, um 
ihn z.B. freizugeben?

Gar nicht mehr. Game Over.


Also: Das Ergebnis von realloc immer einem Hilfspointer zuweisen, den 
Zielpointer erst dann überschreiben, wenn das Ergebnis nicht NULL ist.

von Leo C. (rapid)


Lesenswert?

Peter II schrieb:
> char* RecPointer = (char*) malloc(sizeof(char) * strlen(buf));

Das war oben schon falsch. Richtig ist:
1
char* RecPointer = (char*) malloc(strlen(buf) + 1);

Die Multiplikation mit sizeof(char) ist zwar nicht falsch, kann aber 
weggelassen werden, da sizeof(char) immer 1 ist.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.