Valgrind
-
Schauen Sie sich folgendes Programm an:
#include <iostream> using namespace std; int main() { double null; double *a = new double[5]; a[0] = !null; a[1] = 1; for(int i=1;i<=5;i++) { double tmp = a[i-1] + a[i-2]; a[i] = tmp; if(tmp) cout << "Neue Fibonacci-Zahl: "; cout << tmp; cout << endl; } }Mit etwas Glück berechnet es tatsächlich Fibonnaci Zahlen (compiler-abhängig).
(a) Kompilieren Sie das Programm und führen Sie es aus.
(b) Überwachen Sie die Speicherzugriffe des Programms mit valgrind. Kommentieren Sie adzu Zeile 17, die sehr viele Fehlermeldungen erzeugt.
(c) Ordnen Sie jede Meldung von valgrind einem Programmierfehler zu und beheben Sie ihn.
Zu a) Ich habe das Programm kompiliert und ausgeführt:
g++ -g testdatei.cpp -o test test Neue Fibonacci-Zahl: 1 Neue Fibonacci-Zahl: 2 Neue Fibonacci-Zahl: 3 Neue Fibonacci-Zahl: 5 Neue Fibonacci-Zahl: 8Zu b) Mit dem Befehl
valgrind testerscheinen jede Menge Fehler.
Man muss z.B. nach Zeile 19 Folgendes ergänzen:delete []a;also den allozierten Speicherplatz wieder löschen.
Außerdem wird ganz oft angezeigt, dass man in Zeile 17 nicht initialisierte Werte benutzt. Aber ich weiß nicht, wieso das der Fall ist. In Zeile 13 wird tmp doch initialisiert.
Zu c) Naja, wie gesagt: Den Fehler mit dem nicht wieder gelöschten Speicherplatz habe ich behoben und den mit tmp in Zeile 17 noch nicht. Sonst sehe in valgrind keine Fehler.
Edit: Was bedeutet dieses komische "!null"?
-
Fehler finden sich in den Zeilen 9, 13 und 14.
Die Ursachen dieser Fehler sind in den Zeilen 6 und 12 (und ggf. 7) zu suchen.
-
Mir ist nicht ganz klar, was die Fehler sind, würde aber vermuten, dass man vielleicht den Nullzeiger mit null meint?
Also vielleicht die Zeilen 6 und 7 irgendwie so abändern:
double *a=null; a = new double[5]Aber was soll dann dieses
a[0] = !nullsein?
-
LinuxC_newbie schrieb:
Mir ist nicht ganz klar, was die Fehler sind, würde aber vermuten, dass man vielleicht den Nullzeiger mit null meint?
Nein, null meint hier Null
Also vielleicht die Zeilen 6 und 7 irgendwie so abändern:
double *a=null; a = new double[5]Nicht raten, denken! Wozu sollte hier ein Nullzeiger gut sein? Mal angenommen,
null == 0(was es nicht ist, siehe camper), was ist dann!0?
-
Das heißt, in Zeile 6 deklariert man einfach eine double-Variable namens null?
Aber was soll denn dann !null sein?
Der erste Feldeintrag wird ja auf !null gesetzt, aber was soll das sein?
Da es um Fibonacci-Zahlen geht, würde a[0]=0 Sinn machen.
-
LinuxC_newbie schrieb:
Das heißt, in Zeile 6 deklariert man einfach eine double-Variable namens null?
Aber was soll denn dann !null sein?
Höchst wahrscheinlich 1. Ich denke, es kann aber auch 0 sein.
-
out schrieb:
Höchst wahrscheinlich 1. Ich denke, es kann aber auch 0 sein.Huch
Vergiß mein Beitrag. (diese verwirrenden Bezeichner)
-
Was war daran jetzt denn nicht richtig?
Ich bin (wie fast immer) verwirrt.

Edit: Also mein Compiler versteht in diesem Fall unter !null
-
Mal schauen, ob ich das richtig verstanden habe:
Manche Compiler verstehen unter der Negation einer double-Variablen offenbar die Zahl 1.
Hier wäre also a[0] = 1.
Desweiteren kommt ja in der for-Schleife für i=1 dann a[-1] vor und die Frage ist, was das sein soll.
Bei MIR ist es zum Beispiel 2.07338e-317 und da man ja double hat.. würde das wohl auf 0 gerundet.
Somit hätte man hier zufällig die richtigen Zahlen erwischt, sodass sich die gewünschte Ausgabe ergibt.
----Korrekt muss man aber a[0]=0 setzen und die double Variable weglassen oder zum Beispiel double null = 0 setzen und dann a[0]=null.
Entsprechend muss man dann die Schleife anpassen, indem man sie ab 2 starten lässt. dann bekommt man allerdings nur die Fibonacci Zahlen 2, 3 und 5 ausgegeben. Dafür hat man aber ein sauber funktionierendes Programm.
-
Das ganze Programm ist doch absichtlich verwirrend und fehlerhaft geschrieben, das ist doch gerade der Sinn der Aufgabe! Wie würdest du denn naiv die Fibonaccifolge berechnen? Mit welchen Werten fängst du an? Wenn du das weißt, dann kannst du Zeilen 6-10 erklären.
!0 ist true (weil es nicht 0 ist
). true ist 1. Immer. Nicht auf manchen Compilern.Desweiteren kommt ja in der for-Schleife für i=1 dann a[-1] vor und die Frage ist, was das sein soll.
Ich schlage vor: Einer der zu findenden Fehler.
-
SeppJ schrieb:
Wie würdest du denn naiv die Fibonaccifolge berechnen? Mit welchen Werten fängst du an? Wenn du das weißt, dann kannst du Zeilen 6-10 erklären.
Anscheinend geht es ja hier darum, die ersten 5 Fibonacci-Zahlen auszugeben und zwar nach den ersten beiden Gliedern 0 und 1.
Ich würde das so machen:
#include <iostream> using namespace std; int main() { double *a = new double[7]; a[0]=0; a[1]=1; for(int i=2; i<7; i++) { a[i] = a[i-1] + a[i-2]; cout << a[i] << endl; } }
-
Jetzt lass mal die Null am Anfang weg und der Code dürfte dir bekannt vorkommen.
Ich hoffe übrigens mal, dass du das nicht wirklich so machen würdest, sondern dich von dem schlechten Vorbild zu Designfehlern verleiten hast lassen.
-
Es geht mir darum, zu verstehen, wieso der gegebene Code klappen KANN.
Ich sehe nämlich nicht, wieso!...
double null ist irgendeine double-Variable...
Und was ist dann !null?
Ich kapier es nicht.
-
äquivalent wäre
double null; bool b = null; a[0] = !b;
-
Achso!!
double null ist immer der Wert 0?
Ich habe gedacht, dass wäre nur eine Deklination irgendeiner double-Variablen und noch gar nicht initialisiert!
-
void foo(double d) { if (d) cout << "Foo!\n"; } void bar(double d) { if (!d) cout << "Bar!\n"; }Beschreibe mal die Ausgaben von foo und bar für verschiedene, ausgewählte Werte von d.
-
z.B.
foo(0) gibt nichts aus
foo(2) gibt Foo! aus
bar(0) gibt Bar! aus
bar(2) gibt nichts aus
-
Lernst du daraus etwas über
!null?
-
Also anscheinend ist es so, daß mein Compiler einer nicht initialisierten double-Variablen den Wert 0 zuweist, daß dies aber keinesfalls sein muss und stattdessen auch die Speicheradresse zugewiesen werden kann.
Wie auch immer: In beiden Fällen steht in a[0] ein Wert, der nicht erwünscht ist, denn dort soll weder 1 noch irgendeine Negation von einer Speicheradresse stehen (wobei letzteres ja irgendwie auch noch weniger Sinn macht, weil: was soll das Negierte einer Adresse sein?).
-
LinuxC_newbie schrieb:
Also anscheinend ist es so, daß mein Compiler einer nicht initialisierten double-Variablen den Wert 0 zuweist, daß dies aber keinesfalls sein muss und stattdessen auch die Speicheradresse zugewiesen werden kann.
Ehrlich: Ziemlicher Quark. Der Anfang geht noch, aber danach reihst du einfach ein paar Fachwörter aneinander, die du nicht verstehst, von denen du denkst, sie könnten relevant sein.
-
Dann ist es eben Quark!
Ich kann auch nicht mehr als sagen: dass ich es nicht verstehe.
Wenn ich als Antwort Gegenfragen bekomme, die die gleiche Problematik behandeln, dann drehe ich mich notwendigerweisee im Kreis.