Forum: PC-Programmierung Programm stürzt mit Fehlermeldung "Speicherzugriffsfehler (Speicherabzug geschrieben)" ab


von Ivo -. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich bin gerade dabei, ein Programm zu schreiben, dass TicTacToe einmal 
komplett durchrechnet, es ist noch nicht ganz fertig, da wollte ich es 
mal testen und da kam dann bei der Programmausführung diese 
Fehlermeldung:
Speicherzugriffsfehler (Speicherabzug geschrieben)

Googeln hat mir bisher auch nicht viel gebracht.

Falls ihr noch Fragen zum Code habt, stellt sie gerne, ich bin leider 
nicht der geborene Code-Kommentator:-)

Schon mal Danke im Voraus,
Ivo

PS: Ich nutze Linux Mint und habe mit dem G++ folgendermaßen kompiliert:
g++ main.cpp -o main.out

PSPS: Bitte diskutiert nicht über den Sinn, bzw. Unsinn des Programms 
und dass ich keine Makefiles nutze, etc. (Gut, ich hätte vielleicht noch 
die Warnungen aktivieren sollen)

: Verschoben durch User
von Jim M. (turboj)


Lesenswert?

Stack overflow weil berechnen() sich selbst undendlich oft aufruft.

Kann sein dass das der Debugger nicht ordentlich anzeigt, ansonsten 
suchst Du "backtrace".

von ui (Gast)


Lesenswert?

Hilfe zur Selbsthife ist hier angesagt.
Aktiviere erstmal -wall -werror -wpedenatic , und arbeite alle Fehler 
weg.

Noch etwas:
Du hast 4 geschachtelte for Schleifen + Rekursion? Mutig das du das 
überblickst...

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Kompiliere mit "-g" und benutze einen Debugger wie GDB. Der zeigt dir 
bessere Informationen an. Im konkreten Fall hast du eine endlose 
Rekursion gebaut, das stürzt daher mit einem Stack Overflow ab. Bei der 
Entwicklung sollte man grundsätzlich mit "-Wall -Wextra -Werror" 
kompilieren um möglichst viele potentielle Fehler zu finden, aber das 
hilft im konkreten Fall nicht.
1
#define leer 0
2
#define kreis 1
3
#define kreuz 2
4
5
#define breite 3
6
#define hoehe 3
Das ist C-Stil. In C++ sollte man hier unbedingt richtige Konstanten 
benutzen:
1
static constexpr short leer = 0;
2
static constexpr short kreis = 1;
3
static constexpr short kreis = 2;
4
5
static constexpr short breite = 3;
6
static constexpr short hoehe = 3;

Warum überhaupt überall "short"? Für das Feld wäre doch ein "enum" 
passender. Für die Größe und die Laufvariablen ein std::size_t. Für 
"zuege" müsstest du das erreichbare Maximum vorberechnen und einen 
passenden Typ wählen.

Dir ist klar dass zwischenSpeicher ständig überschrieben wird?

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

ui schrieb:
> pedenatic
Meintest du "pedantic", im Deutschen "pedantisch, kleinlich"?

von Ivo -. (Gast)


Lesenswert?

Hallo,
danke schonmal für eure Tipps, der C-Style hängt bei mir immer noch 
drin, naja...
Dass sich berechnen() immer wieder aufruft, hatte ich übersehen, dachte 
die for-Schleifen enden ja irgendwann.
Das mit dem Überschreiben von zwischenSpeicher, darüber muss ich nochmal 
nachdenken, ich sage es euch dann, wenn ich es raushabe, ob das so 
richtig ist oder nicht.

Die Fehlermeldungen-Flags kennt der Compiler angeblich nicht, er sagt 
mir:
g++ TicTacToe.cpp -o main.out -wall -werror -wpedenatic
g++: error: unrecognized command line option ‘-wall’
g++: error: unrecognized command line option ‘-werror’
g++: error: unrecognized command line option ‘-wpedenatic’

Bin ich sehr doof? (So langsam glaube ich nämlich schon ;-))

Danke für eure Geduld,
Ivo

PS: Die Variable zuege war dafür gedacht, zu wissen, wie viele Züge 
schon gezogen wurden, also ob er jetzt einen Kreis oder ein Kreuz setzen 
muss.

von Ivo -. (Gast)


Lesenswert?

Ah, jetzt kennt er die Flags, hatte die ja klein geschrieben...

Beitrag #5323395 wurde von einem Moderator gelöscht.
von M.K. B. (mkbit)


Angehängte Dateien:

Lesenswert?

Ich hab mal meine Version der Datei angehängt und wie ich das ganze in 
C++ schreiben würde. Bei Fragen, gerne schreiben.
Das Problem mit der Endlosrekursion besteht natürlich immer noch.

Durch meine Anpassungen ändert sich an der Funktion nichts, aber das 
manuelle kopieren der Felder fällt weg. Außerdem verwende ich statt der 
Magic Numbers ein Enum.

von Ivo -. (Gast)


Lesenswert?

Hallo,
Supergroßes Dankeschön, so viel Mühe hätte ich mir nicht gemacht, 
wirklich toll von dir!!! Werde ich mich dann mal nach dem Abendessen 
noch mal dransetzen, wirklich vielen Dank!!!

von Ivo -. (Gast)


Lesenswert?

Oh man, abschreiben müsste man können!
Ich habe doch tatsächlich von meinem "Programm-Storyboard" falsch 
abgeschrieben, der berechnungs-Funktionsaufruf darf nur passieren, wenn 
das Feld ungleich null ist, die endlose Rekursion wäre also behoben, 
ich kann es jetzt gerade leider nicht ausprobieren, da ich gerade nur 
von meinem Smartphone aus schreiben kann, werde es dann morgen nochmal 
probieren und berichten.

Ivo

PS: Was ist denn eure bevorzugte GUI für den GDB?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Ivo Z. schrieb:
> PS: Was ist denn eure bevorzugte GUI für den GDB?

Eclipse, das hat gleich noch viele andere praktische Dinge wie 
automatisches Erstellen von makefiles, Git-Anbindung, Auto Completion & 
Highlighting, funktioniert plattformübergreifend.

von Daniel A. (daniel-a)


Lesenswert?

Für sowas nutze ich gerne asan:
1
daniel@colibri:~/projects/test$ g++ -g -Og -ftest-coverage -static-libasan -fsanitize=undefined -fsanitize=address -fstack-protector-all test.c -o test
2
daniel@colibri:~/projects/test$ ./test 
3
ASAN:DEADLYSIGNAL
4
=================================================================
5
==14446==ERROR: AddressSanitizer: stack-overflow on address 0x7ffe7daf0ff8 (pc 0x55ab20b4fbdb bp 0x000000000000 sp 0x7ffe7daf1000 T0)
6
    #0 0x55ab20b4fbda in berechnen() /home/daniel/projects/test/test.c:26
7
    #1 0x55ab20b4fffa in berechnen() /home/daniel/projects/test/test.c:45
8
    #2 0x55ab20b4fffa in berechnen() /home/daniel/projects/test/test.c:45
(geht noch ne weile so weiter)
1
    #250 0x55ab20b4fffa in berechnen() /home/daniel/projects/test/test.c:45
2
    #251 0x55ab20b4fffa in berechnen() /home/daniel/projects/test/test.c:45
3
4
SUMMARY: AddressSanitizer: stack-overflow /home/daniel/projects/test/test.c:26 in berechnen()
5
==14446==ABORTING

Das ist unglaublich praktisch und funktioniert noch bei vielen ähnlichen 
Problemen. Ich lasse meine Makefiles häufig noch Debug versionen und 
Tests mit dem address sanitizer und co. bauen. (Bei Tests nutze ich auch 
noch "-fprofile-arcs" für die coverage anzeige).

von Rolf M. (rmagnus)


Lesenswert?

Alternativ bietet sich auch immer valgrind für sowas an.
1
$ valgrind ./TicTacToe 
2
==25347== Memcheck, a memory error detector
3
==25347== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
4
==25347== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
5
==25347== Command: ./TicTacToe
6
==25347== 
7
==25347== Stack overflow in thread #1: can't grow stack to 0xffe801000
8
==25347== 
9
==25347== Process terminating with default action of signal 11 (SIGSEGV)
10
==25347==  Access not within mapped region at address 0xFFE801FF8
11
==25347== Stack overflow in thread #1: can't grow stack to 0xffe801000
12
==25347==    at 0x108A46: berechnen() (TicTacToe.cpp:45)
13
==25347==  If you believe this happened as a result of a stack
14
==25347==  overflow in your program's main thread (unlikely but
15
==25347==  possible), you can try to increase the size of the
16
==25347==  main thread stack using the --main-stacksize= flag.
17
==25347==  The main thread stack size used in this run was 8388608.
18
==25347== Stack overflow in thread #1: can't grow stack to 0xffe801000
19
==25347== 
20
==25347== Process terminating with default action of signal 11 (SIGSEGV)
21
==25347==  Access not within mapped region at address 0xFFE801FF0
22
==25347== Stack overflow in thread #1: can't grow stack to 0xffe801000
23
==25347==    at 0x4A286B0: _vgnU_freeres (in /usr/lib/valgrind/vgpreload_core-amd64-linux.so)
24
==25347==  If you believe this happened as a result of a stack
25
==25347==  overflow in your program's main thread (unlikely but
26
==25347==  possible), you can try to increase the size of the
27
==25347==  main thread stack using the --main-stacksize= flag.
28
==25347==  The main thread stack size used in this run was 8388608.
29
==25347== 
30
==25347== HEAP SUMMARY:
31
==25347==     in use at exit: 72,704 bytes in 1 blocks
32
==25347==   total heap usage: 1 allocs, 0 frees, 72,704 bytes allocated
33
==25347== 
34
==25347== LEAK SUMMARY:
35
==25347==    definitely lost: 0 bytes in 0 blocks
36
==25347==    indirectly lost: 0 bytes in 0 blocks
37
==25347==      possibly lost: 0 bytes in 0 blocks
38
==25347==    still reachable: 72,704 bytes in 1 blocks
39
==25347==         suppressed: 0 bytes in 0 blocks
40
==25347== Rerun with --leak-check=full to see details of leaked memory
41
==25347== 
42
==25347== For counts of detected and suppressed errors, rerun with: -v
43
==25347== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
44
Speicherzugriffsfehler (Speicherabzug geschrieben)

von tictactoe (Gast)


Lesenswert?

Ivo Z. schrieb:
> PS: Was ist denn eure bevorzugte GUI für den GDB?

KDbg natürlich: http://www.kdbg.org/

von Hulk (Gast)


Lesenswert?

Valgrind, gibt es klickbar für Eclipse.

-Wall usw. bitte aktivieren. -O2 kann auch nicht schaden.

von Ivo -. (Gast)


Lesenswert?

Hallo,
ich habe es jetzt geschafft, als GUI habe ich Nimever benutzt, die 
endlose Rekursion ist weg, jetzt muss ich noch ein paar Sachen 
hinzufügen, beispielsweise für Berechnungen, die nur bis Zug x gehen 
sollen.

Ivo

PS: Großes Dankeschön an alle!!!

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.