Hallo Gemeinde,
Ich habe ein Problem beim Tausch von Werten eines Structs innerhalb
einer Liste. Beim ersten Mal tausche ich die Werte ohne Probleme. Da ich
sie aber nun zurück tauschen will, tritt ein Speicherzugriffsfehler auf
und ich kann mir nicht erklären, wo dieser liegen soll.
Das Programm soll eine Liste von Dominosteinen so in einem Kreis
anornden, dass dieser geschlossen ist. Beispielsweise soll, wenn die
rechte Hälfte des Dominosteins eine 11 ist, der passende Dominostein
gefunden werden und so gedreht werden, dass die 11 links, also dazu
passend, ist. Hier der Quelltext auszugsweise:
Ich übergebe der Funktion den head einer Liste, so viel zur Erläuterung.
Mein zweites Problem dann ist, dass ich ja grundsätzlich die Liste mit
jedem Listenelement am Anfang ausgeben will, sodass die oben genannte
Bedingung erfüllt ist. Nun ist es so, dass bei gewissen Datein das
Programm sich in einer Endlosschleife aufhängt und bei manchen Datein
macht er das bis zum letzten Element, gibt da allerdings nur den
Listenkopf aus. Wie oben aufgezeigt, vertausche ich nicht die ganzen
Elemente, sondern lediglich die gespeicherten Zahlenwerte. Woran liegt
das Problem hier?
valgrind (bzw. memcheck, das Default-Tool) ist ein "memory error
detector", der dir genau sagen kannst, wann und von wo du zum Beispiel
uninitialisierten Speicher liest, außerhalb von Array-Grenzen schreibst,
auf gelöschte Objekte zugreifst etc. Die meisten komischen
C++-Speicherfehler hat man damit sehr schnell gefunden.
Sven B. schrieb:> valgrind (bzw. memcheck, das Default-Tool) ist ein "memory error> detector", der dir genau sagen kannst, wann und von wo du zum Beispiel> uninitialisierten Speicher liest, außerhalb von Array-Grenzen schreibst,> auf gelöschte Objekte zugreifst etc. Die meisten komischen> C++-Speicherfehler hat man damit sehr schnell gefunden.
Und wie genau implementiere ich ihn innerhalb meines Cods?
Carl D. schrieb:> Was daran ist eigentlich C++?> Wenn es C++ wäre, dann gäbe es da std::list<> (besser std::vector<>) und> kein Speicherproblem.
Speicherplatz anfordern mit new.
Darf ich nicht nutzen.
Max F. schrieb:> Carl D. schrieb:>> Was daran ist eigentlich C++?>> Wenn es C++ wäre, dann gäbe es da std::list<> (besser std::vector<>) und>> kein Speicherproblem.>> Speicherplatz anfordern mit new.> Darf ich nicht nutzen.
Der STL kannst du deine eigene allocator Klasse in die Hand drücken, die
dann statt der Standard-Heap Implementierung benutzt wird.
The D. schrieb:> Max F. schrieb:>> Carl D. schrieb:>>> Was daran ist eigentlich C++?>>> Wenn es C++ wäre, dann gäbe es da std::list<> (besser std::vector<>) und>>> kein Speicherproblem.>>>> Speicherplatz anfordern mit new.>> Darf ich nicht nutzen.>> Der STL kannst du deine eigene allocator Klasse in die Hand drücken, die> dann statt der Standard-Heap Implementierung benutzt wird.
Das Problem ist, ich darf die Aufgabe nur mit den im Programm genutzen
Werkzeug lösen. Das macht die Sache erheblich schwerer.
The D. schrieb:> Max F. schrieb:>> Carl D. schrieb:>>> Was daran ist eigentlich C++?>>> Wenn es C++ wäre, dann gäbe es da std::list<> (besser std::vector<>) und>>> kein Speicherproblem.>>>> Speicherplatz anfordern mit new.>> Darf ich nicht nutzen.>> Der STL kannst du deine eigene allocator Klasse in die Hand drücken, die> dann statt der Standard-Heap Implementierung benutzt wird.
Ich glaube er meinte, er darf die STL nicht benutzen, new aber schon, da
es ja ein Sprachelement von C++ ist.
Klingt nach Schule oder untere Semester. Ich hoffe nach der Übung sagt
der Lehrer/Prof. "so und jetzt das ganze mal mit STL, ganz knapp und
stabil".
(man darf ja hoffen, oder? Auch wenn's sicher vergeblich ist ;-)
Carl D. schrieb:> The D. schrieb:>> Max F. schrieb:>>> Carl D. schrieb:>>>> Was daran ist eigentlich C++?>>>> Wenn es C++ wäre, dann gäbe es da std::list<> (besser std::vector<>) und>>>> kein Speicherproblem.>>>>>> Speicherplatz anfordern mit new.>>> Darf ich nicht nutzen.>>>> Der STL kannst du deine eigene allocator Klasse in die Hand drücken, die>> dann statt der Standard-Heap Implementierung benutzt wird.>> Ich glaube er meinte, er darf die STL nicht benutzen, new aber schon, da> es ja ein Sprachelement von C++ ist.> Klingt nach Schule oder untere Semester. Ich hoffe nach der Übung sagt> der Lehrer/Prof. "so und jetzt das ganze mal mit STL, ganz knapp und> stabil".> (man darf ja hoffen, oder? Auch wenn's sicher vergeblich ist ;-)
2. Semester ;)
Den Speicherzugriffsfehler habe ich gelöst, danke an dieser Stelle für
die Hilfe.
Allerdings besteht das 2. Problem immernoch, keine Ahnung, ob es hier
passend ist.
Die eine Datei liest er zweifelsfrei, bei der anderen gerät er nach der
Ausgabe des 2. neuen Heads in eine Endlosschleife. Ich muss erstmal
gucken, in welcher.
Vielleicht solltest du das ganze in die Komponenten Swap, Sort und
Compare zerlegen. Diese sind dann jeweils kleiner und überschaubarer.
Das was du hier machst, ist nämlich die Aufgabe des Compilers(/Linkers):
aus der strukturierten Lösungsbeschreibung per Optimierung möglichst
Branchfreien, auch Spagetti-Code genannten, Maschinen-Code zu
produzieren. Jeder halbwegs vernünftige Compiler wird auf ein Resultat
kommen, das bei dir schon im Sourcecode vorhanden ist und leicht
unübersichtlich wirkt.
Da es a C++ sein soll, darf die struct auch diese Methoden besitzen:
Sort(), Swap() und Compare() oder auch operator<(), oder?
Carl D. schrieb:> Vielleicht solltest du das ganze in die Komponenten Swap, Sort und> Compare zerlegen. Diese sind dann jeweils kleiner und überschaubarer.> Das was du hier machst, ist nämlich die Aufgabe des Compilers(/Linkers):> aus der strukturierten Lösungsbeschreibung per Optimierung möglichst> Branchfreien, auch Spagetti-Code genannten, Maschinen-Code zu> produzieren. Jeder halbwegs vernünftige Compiler wird auf ein Resultat> kommen, das bei dir schon im Sourcecode vorhanden ist und leicht> unübersichtlich wirkt.> Da es a C++ sein soll, darf die struct auch diese Methoden besitzen:> Sort(), Swap() und Compare() oder auch operator<(), oder?
Das wäre dann aber ein abstrakter Datentyp (=Class) und kein Struct mehr
;)
Das mit den in Unterfunktionen zu untergliedern, ist sicher richtig,das
ist auch zugegebenermaßen meine Schwäche :D
Ich habe es aber jetz einmal bis hier hin, das würde ich ungern über den
Haufen werfen.
Die fehlerhafte Schleife habe ich zwar gefunden, den Fehler da drin aber
noch nicht.
Das ist der aktuelle Stand der Dinge:
1
voidsortieren(node*head,intanzahl){
2
node*new_head,*start,*pos,*aktuell,*temp,*tausch;
3
intswap;
4
inti=0;
5
intj=0;
6
intk=0;
7
intstelle=0;
8
intzahl_links,zahl_rechts;
9
node*feld[anzahl];
10
11
aktuell=head;
12
while(aktuell!=0){
13
aktuell->markiert=false;
14
aktuell->getauscht=false;
15
aktuell=aktuell->next;
16
}
17
18
new_head=newnode;
19
new_head->zahl_l=head->zahl_l;
20
new_head->zahl_r=head->zahl_r;
21
new_head->next=0;
22
pos=head->next;
23
aktuell=head->next;
24
25
start=head;
26
while(start!=NULL){
27
aktuell=head;
28
while(aktuell!=0){
29
aktuell->markiert=false;
30
aktuell=aktuell->next;
31
}
32
tausch=newnode;
33
new_head=newnode;
34
new_head->zahl_l=head->zahl_l;
35
new_head->zahl_r=head->zahl_r;
36
new_head->next=0;
37
pos=head->next;
38
aktuell=head->next;
39
40
tausch->zahl_l=new_head->zahl_l;
41
tausch->zahl_r=new_head->zahl_r;
42
if(start->getauscht!=true){// löst den Speicherzugriffsfehler übrigens
Die Liste
1 3 (= Dominostein mit links 1 und rechts 3)
3 5
2 6
6 23
23 42
2 42
1 5
liefert nach Abbruch folgendes, fehlerhaftes Ergebnis:
[1;3][3;5][5;1] (richtig)
[3;5] (falsch, keine Ahnung was er hier macht)
[2;6][6;23][23;42][42;23][23;42][42;23][23;42][42;23] (falsch)
[6;23][23;42][42;2][2;6] (richtig)
[42;23][23;6][6;2][2;42] (falsch, da er eigentlich mit [23;42] beginnen
muss)
[42;2][2;6][6;23][23;6][6;23][23;6][6;23][23;6] (falsch)
[1;5][5;3][3;1] (richtig)
Wenn ich die Sache nicht nach 7 Durchläufen abbrechen würde, würde er
sich irgendwann in der Dauerschleife verlieren und nur noch [23;42] und
[42;23] jeweils im Wechsel ausgeben. Woran könnte das liegen?
In C++ unterscheidet sich eine struct von der class nur durch den
Defaultwert für die Komponentensichbarkeit. Bei class ist diese private,
bei einer struct ist sie public.
Carl D. schrieb:> In C++ unterscheidet sich eine struct von der class nur durch den> Defaultwert für die Komponentensichbarkeit. Bei class ist diese private,> bei einer struct ist sie public.
Stimmt, im Struct sind alle Methoden grundsätzlich Public.
Nichtsdestotrotz hilft mir das im Moment nicht weiter und mir ist es
leider auch nicht gelungen die Fehlerquelle weiter einzugrenzen.
Max F. schrieb:> Nichtsdestotrotz hilft mir das im Moment nicht weiter und mir ist es> leider auch nicht gelungen die Fehlerquelle weiter einzugrenzen.
Hast du denn mal einen Debugger benutzt? Sorry, ich habe keine Lust mich
in diesen Code einzulesen, das musst du im Detail schon selber tun ...
Max F. schrieb:> Carl D. schrieb:>> In C++ unterscheidet sich eine struct von der class nur durch den>> Defaultwert für die Komponentensichbarkeit. Bei class ist diese private,>> bei einer struct ist sie public.>> Stimmt, im Struct sind alle Methoden grundsätzlich Public.>> Nichtsdestotrotz hilft mir das im Moment nicht weiter und mir ist es> leider auch nicht gelungen die Fehlerquelle weiter einzugrenzen.
Meine Idee (am Anfang) war ja auch eher dich zu Gedanken über dein
Nudelprogramm anzuregen. Eine seiner Nachteil erlebst du ja gerade.