Forum: PC-Programmierung Memory Leak?


von inok (Gast)


Lesenswert?

Hi,

mich würde interessieren, ob der folgende Code-Schnipsel den gesamte 
Speicher der reserviert wurde, auch tatsächlich wieder freigegeben wird. 
Oder habe ich da was übersehen, bzw. falsch angewendet? Ich bitte um 
kurze Stellungnahme :-) Danke.
Gibt es dafür Tools, mit denen ich mir solche Fragen selber beantworten 
kann?
1
#define ANZAHL_ZEILEN   ((int)7)
2
#define ANZAHL_SPALTEN  ((int)10)
3
4
int** AllocateMatrixMemory();
5
void FreeMatrixMemory(int** matrix);
6
7
int main()
8
{
9
    int** matrixA = AllocateMatrixMemory();
10
11
    FreeMatrixMemory(matrixA);
12
13
    return 0;
14
}
15
16
int** AllocateMatrixMemory()
17
{
18
    int** returnValue = 0;
19
    int i = 0;
20
21
    returnValue = ((int**)malloc(sizeof(int*) * ANZAHL_ZEILEN));
22
23
    for (i = 0; ANZAHL_ZEILEN > i; i++)
24
    {
25
        returnValue[i] = ((int*)malloc(sizeof(int) * ANZAHL_SPALTEN));
26
    }
27
28
    return returnValue;
29
}
30
31
void FreeMatrixMemory(int** matrix)
32
{
33
    int i = 0;
34
35
    for (i = 0; ANZAHL_ZEILEN > i; i++)
36
    {
37
        free(matrix[i]);
38
    }
39
40
    free(matrix);
41
}

Danke. Gruß
inok

: Verschoben durch Admin
von Karl H. (kbuchegg)


Lesenswert?

inok schrieb:

> mich würde interessieren, ob der folgende Code-Schnipsel den gesamte
> Speicher der reserviert wurde, auch tatsächlich wieder freigegeben wird.

Tut er

> Gibt es dafür Tools, mit denen ich mir solche Fragen selber beantworten
> kann?

Sicher gibt es die.
Tools wie Bounds Checker können das.
VC++ kann das auch in der Debug Version machen.

Und zu guter letzt kann man sich auch selbst etwas schreiben:
* ein eigenes my_malloc, welches den von malloc gelieferten Pointer in 
eine Liste einträgt
* ein eigenes my_free, welches den vom Programm zurückgegebenen Pointer 
in der Liste sucht. Ist der nicht drinnen, versucht man gerade denselben 
Speicherbereich 2 mal freizugeben
* Am Ende des Programmlaufs muss die Liste wieder leer sein, ansonsten 
leaked das Programm


In deinem Fall reicht es aber die Anzahl der Aufrufe zu malloc zu 
zählen, die Anzahl der Aufrufe zu free zu zählen, und da beide Anzahlen 
gleich sind, leaked das Programm auch nicht.

von Karl H. (kbuchegg)


Lesenswert?

1
for (i = 0; ANZAHL_ZEILEN > i; i++)

gewöhn dir das wieder ab.

Die kanonische for-Schleife, die über alle Elemente eines Arrays geht, 
lautet
1
  for( i = 0; i < Arraygröße; i++ )

Deine for-Schleife ist zwar dazu äquivalent, trotzdem sieht sie anders 
aus und erfordert genaueres Hinsehen um zu erkennen, dass du einfach nur 
ein i über alle Elemente eines Arrays haben willst.

Die 2te Form wird von Millionen von Programmierern weltweit eingesetzt 
und im Halbschlaf erkannt. Es ist keine gute Idee, aus keinem wirklich 
guten Grund heraus eine eigene Form dafür zu erfinden.

von inok (Gast)


Lesenswert?

Hi,

erstmal danke für deine Mühe.
Bei solchen Abbruchbedingungen schreiben ich bei Möglichkeit immer die 
konstanten als lvalue, um einen möglichen Typfehler (Zuweisung) mit 
einem Compile-Fehler zu erkennen. Somit tritt z.B. ein Fehler dieser Art
1
while (exit = false)

durch
1
while (false = exit)

nicht mehr auf. Bzw. der Compiler weißt mich auf diesen Fehler hin.

Gruß
inok

von Karl H. (kbuchegg)


Lesenswert?

inok schrieb:

> einem Compile-Fehler zu erkennen. Somit tritt z.B. ein Fehler dieser Art

Wie oft hast du denn den Fehler gemacht, als du es noch anders rum 
geschrieben hast? (Deine ersten 20 Stunden Programmierung mal 
ausgeklammert)

Eben.

Die meisten Programmierer die ich kenne, geben diese Schreibweise wieder 
auf, weil sie vor einem Fehler schützt, der in der Praxis selten genug 
vorkommt (und von vielen Compilern sowieso angewarnt wird). Meistens 
wird dem besseren Lesefluss der Vorzug gegeben. Wir sprechen (und 
denken) nun mal "Wenn die Uhr 5 Stunden anzeigt". Also zuerst "welches 
variable Ding" und dann erst "welchen Wert muss es haben"

"Wenn die Anzahl der Teller im Geschirrspüler größer als 5 ist, dann die 
Maschine einschalten."

"Wenn 5 kleiner oder gleich der Anzahl Teller ist, dann die Maschine 
einschalten."

Welcher Satz kommt deiner 'natürlichen Denkweise' näher?

Ausserdem hast du hier keine Zuweisung bzw. einen Vergleich auf 
Gleichheit. Damit stellt sich dieses 'Problem' an dieser Stelle gar 
nicht.

Aber es ist ok. Des Menschen Wille ist sein Himmelreich. Sobald du mit 
anderen Entwicklern zusammenarbeiten musst, werden die dir diese 
Schreibweise schon austreiben :-)

von madler (Gast)


Lesenswert?

Ja, bei if oder while mit == macht das auch Sinn, bei for, wo ja selten 
ein == in der Bedingung stehen wird und generell bei > oder <, nicht.

von g457 (Gast)


Lesenswert?

> Somit tritt z.B. ein Fehler dieser Art
> while (exit = false)

..ein anständiger Compiler meckert auch sowas an, das sieht dann z.B. so 
aus:
1
$ cat foo.cpp 
2
void foo()
3
{
4
        bool bExit;
5
6
        while (bExit = false)
7
        {
8
                // foo(bar);
9
        }
10
}
11
$ gcc -Wall -c foo.cpp -o foo.o
12
foo.cpp: In function ‘void foo()’:
13
foo.cpp:5: warning: suggest parentheses around assignment used as truth value

Warnings sind halt dafür da, dass sie nicht ignoriert werden ;-)

von inok (Gast)


Lesenswert?

Ich bin selber Fachinformatiker Anwendungsentwicklung und arbeite auch 
mit anderen Entwicklern zusammen. Nur mache ich das erst seit knapp 4 
jahren. Wie ich momentan mitbekomme, sammle ich jetzt erst die gesamten 
Feinheiten (?) der Programmentwicklung in C/C++, worein auch solche 
Stil-Dinge fallen. Dieser Art von Ausdruck halt aus der rein 
fehler-anfälligen Seite her gesehen.

Gruß
inok

von Karl H. (kbuchegg)


Lesenswert?

inok schrieb:
> Ich bin selber Fachinformatiker Anwendungsentwicklung und arbeite auch
> mit anderen Entwicklern zusammen. Nur mache ich das erst seit knapp 4
> jahren. Wie ich momentan mitbekomme, sammle ich jetzt erst die gesamten
> Feinheiten (?) der Programmentwicklung in C/C++, worein auch solche
> Stil-Dinge fallen. Dieser Art von Ausdruck halt aus der rein
> fehler-anfälligen Seite her gesehen.

Sollte ja kein Vorwurf sein.
Ich weiß, diesen Rat liest man auch in vielen Büchern und er wird auch 
gerne in Styleguides gegeben.
Die tatsächliche Praxis ist aber so, dass gerade bei mehr Erfahrung 
dieses sog. 'Problem' gar keines ist. Ich kann mich gar nicht mehr 
erinnern, wann es mir tatsächlich passiert ist, ungewollt eine Zuweisung 
anstelle eines == zu schreiben. Und ich bin seit 25 Jahren im Geschäft.
Ich kann mich aber noch sehr gut erinnern, wann ich das letzte mal 
derartig 'verquerte' Logik auf normale Denkweise umzustellen hatte, um 
zu merken dass sich der Autor vertan hat.
Machs ruhig bei ==, wenn du dich damit sicherer fühlst. Aber belasse es 
bei allen anderen Vergleichen bei der normalen Leserichtung.

In ein paar Jahren wird es dir auch so ergehen
Du liest

   for( j = 0; j < ARRAY_SIZE; ++j )
     mach was mit daten[j];

Du liest das gar nicht mehr richtig. Deine Augen scannen die erste Zeile 
ab, stellen in Sekundenbruchteilen fest das alles so aussieht wie es 
aussehen soll:

*  = 0 ?                                                 ist da
*  < irgendwas ?                                         ist da
*  ++                                                    ist da
*  überall dieselbe Variable                             ist da
*  Variable wird im Block als Index benutzt              ist da
*  das 'irgendwas' korreliert mit der Arraydefinition    ist da

und du analysierst da nicht mehr lange. Das ist eine typische Schleife, 
die mit allen Elementen eines Arrays etwas in aufsteigender Reihenfolge 
macht.
Und das gute ist: Diese Schleife findest du in genau derselben Form bei 
mehr als 95% aller C-Programmierer weltweit wieder. Egal ob das ein 
Japaner oder ein Amerikaner geschrieben hat. Sie sieht immer gleich aus.
Nur wenn irgendeines der Kriterien nicht erüllt ist, wirst du plötzlich 
hell wach und fragst dich, warum deine Erwartung einer Array-Index 
Schleife nicht erfüllt wird, nur um dann festzustellen, das ohnehin 
alles in Ordnung ist, und der Autor nur eine 'unübliche' Schreibweise 
gewählt hat.
Progamme analysieren hat sehr viel mit Muster erkennen zu tun. Das geht 
bei fremdem Code umso besser, je mehr Muster überall in gleicher Form 
eingesetzt werden.

von Olaf D. (Firma: O.D.I.S.) (dreyero)


Lesenswert?

Hallo inok,

um mal auf die ursprüngliche Frage nach den Tools zurückzukommen:
Ich entwickele sehr viel unter Linux und dort teste ich die Software
immer mit valgrind auf MemoryLeaks.

http://www.valgrind.org


Gruß

Olaf

von Oliver R. (superberti)


Lesenswert?

Hi,

100% Ack für Karl Heinz.
Ich habe darüber noch nie so genau nachgedacht, aber man stolpert 
tatsächlich über solch "komische" Zeilen mit umgedrehter Logik. Niemand 
aus unser Gruppe (alle > 10 Jahre BA) macht das so...

Achja, Profiler wie z.B. AQTime können Leaks auch ganz gut erkennen...

Gruß,

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Oliver R. schrieb:
> Hi,
>
> 100% Ack für Karl Heinz.
> Ich habe darüber noch nie so genau nachgedacht, aber man stolpert
> tatsächlich über solch "komische" Zeilen mit umgedrehter Logik.

Als ich weiter oben das Tellerbeispiel kreiert hatte, hatte ich 
ursprünglich
1
Wenn die Anzahl der Teller größer 5 ist, ..
2
3
Wenn 5 kleiner als die Anzahl der Teller ist, ...
und ich hab gut und gerne 2 Minuten (und mit Finger abzählen, 
Zahlengerade aufmalen, Teller auf Papier aufmalen) damit verbracht, mich 
davon zu überzeugen, dass das falsch ist und 'kleiner oder gleich' 
heissen muss.

Da sieht man wieder: So schreiben wie man denkt. Dann stehen die Chancen 
gut, dass es richtig wird. Wenn man in eine Programmzeile lediglich ein 
paar Füllwörter einfügen muss, die Zeile ansonsten aber als normalen 
Satz lesen kann, dem man nach 3 Sekunden Nachdenken zustimmen kann und 
der nicht komisch klingt, hat man das meiste richtig gemacht.
Lediglich bei AND und OR sollte man der gesprochenen Sprache nicht 
trauen. Speziell wenn dann noch ein NICHT ins Spiel kommt, meinen wir 
zwar oft das Richtige, sagen aber Unsinn (Stichwort: De Morgan)

von der mechatroniker (Gast)


Lesenswert?

@KHB: Leider hast du zu lange drüber nachgedacht... Deine ursprüngliche 
Umwandlung war richtig. a < b gibt b > a

von Andreas F. (aferber)


Lesenswert?

Karl heinz Buchegger schrieb:
>
1
> Wenn die Anzahl der Teller größer 5 ist, ..
2
> 
3
> Wenn 5 kleiner als die Anzahl der Teller ist, ...
4
>
> und ich hab gut und gerne 2 Minuten (und mit Finger abzählen,
> Zahlengerade aufmalen, Teller auf Papier aufmalen) damit verbracht, mich
> davon zu überzeugen, dass das falsch ist und 'kleiner oder gleich'
> heissen muss.

Und hier hast du dir selbst eine Falle gestellt, du hast nicht die 
Schreibweise des Ausdrucks umgedreht, sondern ihn negiert, also die 
Logik "umgedreht" ;-)

Die einfachen Relationen (=, >, <, >=, <=, sowas) kann man tatsächlich 
einfach "spiegeln", also Seiten vertauschen und ">" und "<" 
gegeneinander austauschen.

Andreas

von Karl H. (kbuchegg)


Lesenswert?

Puh
War beim Burger King und diese Umkehrung hat mich nicht los gelassen :-)

von inok (Gast)


Lesenswert?

Nene, wurde nicht als Vorwurf aufgefasst :-)
Ich finde es gut solche Dinge zu erfahren. Nach den 3 Jahren Ausbildung 
+ knapp 1 Jahr Berufspraxis sitzt halt noch lange nicht alles, ganz 
klar! Und der eigene Stil lässt sowieso noch auf sich warten...
Werde das Forum mal zu meinen Lesezeichen hinzufügen, sammelt man doch 
jede Menge Eindrücke auch einfach nur beim Lesen.

Gruß
inok

von A. Nonym (Gast)


Lesenswert?

Moin,

schon etwas älter und leicht OT, aber sei es drum...

>Diese Schleife findest du in genau derselben Form bei
>mehr als 95% aller C-Programmierer weltweit wieder. Egal ob das ein
>Japaner oder ein Amerikaner geschrieben hat. Sie sieht immer gleich aus.
>Nur wenn irgendeines der Kriterien nicht erüllt ist, wirst du plötzlich
>hell wach und fragst dich, warum deine Erwartung einer Array-Index
>Schleife nicht erfüllt wird, nur um dann festzustellen, das ohnehin
>alles in Ordnung ist, und der Autor nur eine 'unübliche' Schreibweise
>gewählt hat.
>Progamme analysieren hat sehr viel mit Muster erkennen zu tun. Das geht
>bei fremdem Code umso besser, je mehr Muster überall in gleicher Form
>eingesetzt werden.


Ja, unbedingt die übliche Schreibweise verwenden. Umgekehrt (ANZAHL>i) 
funktioniert es zwar auch, aber man stolpert beim Lesen drüber. Da 
helfen auch keine Kommentare, sowas sollte der geübter Programmierer 
ohne erkennen. Ganz im Gegenteil, ein Kommentar an dieser Stelle bläht 
die Datei nur unnötig auf.

An der Uni muss man jeden Forz kommentieren, persönlich mache ich davon 
wenig Gebrauch, trotz teils haariger Schreibweisen. C ist da ein 
wunderbarer Spielplatz, man kann es "Anfängerkompatibel" lang und extra 
dick kommentiert, im üblichen Standardstil oder ganz kurz und knackig 
(und unleserlich und fehleranfällig...) schreiben...

Es gilt das Motto "If you can say it with code, code it, else comment 
it."

(Informatiker sind faul ;-) )

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.