Forum: PC-Programmierung Programmabsturz - Fehler unbekannt


von Daniel S. (dani2304)


Lesenswert?

Hallo,
ich muss ein Sodoku Spiel programmieren, aber weiß nicht wieso mein 
Programm bei der Überprüfung der Zeilen abstürzt...
1
    void sodokuCheck(char **spielfeld){
2
    int i,j,pruef=0;
3
    for(j=2;j<7;j+=2)
4
    {
5
            for(i=2;i<7;i+=2){
6
                    pruef=0;
7
                    printf("%i,%i",i,j);
8
                if(spielfeld[i][j]!=spielfeld[i+2][j] && spielfeld[i[j]!=spielfeld[i+4][j] && spielfeld[i][j]!=spielfeld[i+6][j]&& i==2){
9
                    printf("Erste");
10
                   pruef=1;
11
                    goto schleife;
12
                }
13
                if(spielfeld[i][j]!=spielfeld[i+2][j] && spielfeld[i[j]!=spielfeld[i+4][j] && i==4){
14
                    printf("Zweite");
15
                    pruef=1;
16
                    goto schleife;
17
                }
18
                if(spielfeld[i][j]!=spielfeld[i+2][j] && i==6){
19
                    printf("Dritte");
20
                    pruef=1;
21
                    goto schleife;
22
                }
23
                printf("Fehler in %i, %i",j,i);
24
                return;
25
                schleife:;
26
        }
27
    }
28
    }

In dem Spielfeld kann man mehrere Zahlen eingeben und diese Funktion 
soll üerprüfen ob die Zahl in jeder Spalte nur einmal vorkommt. Habe 
aber keine Ahnung warum das Programm abstürzt. Habe einen ähnlichen Code 
bei der Überprüfung der Spalten und dort funktioniert es.


MfG

von Peter II (Gast)


Lesenswert?

Daniel S. schrieb:
> aber weiß nicht wieso mein
> Programm bei der Überprüfung der Zeilen abstürzt...

wir auch nicht. Zum helfen brauchen wir mehr code.

wie groß wird spielfeld angelegt?

von Peter II (Gast)


Lesenswert?

Nachtrag:

das goto ist böse - verwende continue in der schleife, dann brauchst du 
es nicht.

von guest (Gast)


Lesenswert?

Wenn Dein Speilfeld nicht mindestens als
1
char * spielfeld[13][7];
deklariert ist knallt es.

Außerdem passt Dein Funktionsparameter "char **spielfeld" nicht wirklich 
zu den Zugriffen darauf (z.B. "spielfeld[i][j]"). Addressen von 
Zeichenketten zu vergleichen macht nur sehr selten wirklich Sinn.

von Peter II (Gast)


Lesenswert?

guest schrieb:
> Außerdem passt Dein Funktionsparameter "char **spielfeld" nicht wirklich
> zu den Zugriffen darauf (z.B. "spielfeld[i][j]"). Addressen von
> Zeichenketten zu vergleichen macht nur sehr selten wirklich Sinn.


stimmt, 2 dimensionale Array kann man nicht universell an eine Funktion 
übergeben, das geht einfach nicht.

von Daniel S. (dani2304)


Lesenswert?

1
#include <stdio.h>
2
#include <stdlib.h>
3
#define GROESSE_FELD 4
4
#define DIM_ZEILE (GROESSE_FELD * 2+2)
5
#define DIM_SPALTE (GROESSE_FELD * 2+2)
6
7
8
void spielGeruest(char **spielfeld){
9
int i=0, j=0;
10
spielfeld[0]=" 012345678";
11
spielfeld[1][0]='0';
12
spielfeld[2][0]='1';
13
spielfeld[3][0]='2';
14
spielfeld[4][0]='3';
15
spielfeld[5][0]='4';
16
spielfeld[6][0]='5';
17
spielfeld[7][0]='6';
18
spielfeld[8][0]='7';
19
spielfeld[9][0]='8';
20
21
for (i=1 ;i<(DIM_ZEILE); i++){
22
    for(j=1;j<(DIM_SPALTE);j++){
23
        if((i%2)){
24
            if((j%2)){
25
                spielfeld[i][j]='|';
26
        }
27
        else{
28
            spielfeld[i][j]='-';
29
30
        }
31
        }
32
        else{
33
            if((j%2)){
34
                spielfeld [i][j]='|';
35
            }
36
            else{
37
                spielfeld [i][j]='x';
38
            }
39
        }
40
        spielfeld[i][j+2]='\0';
41
    }
42
}
43
}
44
45
46
47
48
void ausgabeSpielfeld(char **spielfeld){
49
    int i=0;
50
    for(i=0;i<DIM_SPALTE;i++)
51
    printf("%s\n",*(spielfeld+i));
52
53
}
54
55
void sodokuVorlage(char **spielfeld){
56
    int i=0, j=0,x=0,y=0;
57
    for(i=0;i<DIM_ZEILE;i++)
58
    {
59
        for(j=0;j<DIM_SPALTE;j++)
60
        {
61
            if(spielfeld[i][j]=='x')
62
            {
63
                printf("Geben sie fuer x=%i und y=%i den gewuenschten Wert ein:",i-1,j-1);
64
                scanf("%c",&spielfeld[i][j]);
65
                fflush(stdin);
66
                while(spielfeld[i][j]!=' ' && spielfeld[i][j]!='1' && spielfeld[i][j]!='2' && spielfeld[i][j]!='3' && spielfeld[i][j]!='4')
67
                {
68
                printf("Falsche Eingabe!\nGeben sie erneut fuer x=%i und y=%i den gewuenschten Wert ein:",i-1,j-1);
69
                scanf("%c",&spielfeld[i][j]);
70
                fflush(stdin);
71
                }
72
                if(j>=9){
73
                    spielfeld[i][j]='\0';
74
                }
75
                fflush(stdin);
76
            }
77
        }
78
79
    }
80
}
81
82
    void sodokuStart(char **spielfeld)
83
    {
84
    int i=0, j=0, z=0,a=0,b=0, pz=0;
85
    int x[10],y[10];
86
87
88
    for(i=1;i<DIM_ZEILE;i++)
89
    {
90
        for(j=1;j<DIM_SPALTE;j++)
91
        {
92
           if(spielfeld[i][j]==' '){
93
                x[z]=i;
94
                y[z]=j;
95
                z++;
96
                pz=1;
97
            }
98
        }
99
    }
100
    while(pz==1){
101
    printf("Bitte geben Sie das zu aendernde Feld ein:\nZeile und Spalte: ");
102
    scanf("%i %i", &a, &b);
103
    fflush(stdin);
104
    a++;
105
    b++;
106
    while((a>9 || b>9)|| (a<=0 || b<=0))
107
    {
108
        printf("Dieses Feld existiert nicht. Bitte geben Sie ihre Eingabe erneut ein:");
109
        scanf("%i %i", &a, &b);
110
        a++;
111
        b++;
112
        fflush(stdin);
113
    }
114
    for(i=0;i<z;i++){
115
    if(x[i]==a && y[i]==b) goto weiter;
116
    }
117
    while(spielfeld[a][b]!=' ')
118
    {
119
        printf("Das ausgewae1hlte Feld darf nicht bearbeitet werden!  Bitte geben Sie ihre Eingabe erneut ein:");
120
        scanf("%i %i", &a, &b);
121
        a++;
122
        b++;
123
        fflush(stdin);
124
    }
125
    weiter: printf("Geben sie die auszufuellende Zahl ein:");
126
    scanf("%c",&spielfeld[a][b]);
127
    fflush(stdin);
128
    while(spielfeld[a][b]!='1' && spielfeld[a][b]!='2' && spielfeld[a][b]!='3' && spielfeld[a][b]!='4') {
129
        printf("Bitte nur eine Zahl zwischen '1' und '4' waehlen:");
130
        scanf("%c", &spielfeld[a][b]);
131
        fflush(stdin);
132
    }
133
    pz=0;
134
    for(i=1;i<DIM_ZEILE;i++)
135
    {
136
        if(pz==1) break;
137
        for(j=1;j<DIM_SPALTE;j++)
138
        {
139
           if(spielfeld[i][j]==' '){
140
            pz=1;
141
            break;
142
           }
143
           else pz=0;
144
        }
145
    }
146
    ausgabeSpielfeld(spielfeld);
147
    }
148
    }
149
150
    void sodokuCheck(char **spielfeld){
151
    int i,j,pruef=0;
152
    for(j=2;j<7;j+=2)
153
    {
154
            for(i=2;i<7;i+=2){
155
                    pruef=0;
156
                    printf("%i,%i",i,j);
157
                if(spielfeld[i][j]!=spielfeld[i+2][j] && spielfeld[i][j]!=spielfeld[i+4][j] && spielfeld[i][j]!=spielfeld[i+6][j]&& i==2){
158
                    printf("Erste");
159
                   pruef=1;
160
                    goto schleife;
161
                }
162
                if(spielfeld[i][j]!=spielfeld[i+2][j] && spielfeld[i][j]!=spielfeld[i+4][j] && i==4){
163
                    printf("Zweite");
164
                    pruef=1;
165
                    goto schleife;
166
                }
167
                if(spielfeld[i][j]!=spielfeld[i+2][j] && i==6){
168
                    printf("Dritte");
169
                    pruef=1;
170
                    goto schleife;
171
                }
172
                printf("Fehler in %i, %i",j,i);
173
                return;
174
                schleife:;
175
        }
176
    }
177
    }
178
179
180
int main(){
181
    char **Feld;
182
    int i;
183
    Feld=malloc(DIM_ZEILE * sizeof *Feld);
184
    for(i=0;i<DIM_ZEILE;i++){
185
        Feld[i] = malloc(DIM_SPALTE * sizeof **Feld);
186
    }
187
spielGeruest(Feld);
188
ausgabeSpielfeld(Feld);
189
sodokuVorlage(Feld);
190
ausgabeSpielfeld(Feld);
191
sodokuStart(Feld);
192
sodokuCheck(Feld);
193
return 0;
194
}

Hab mal alles gepostet. Ist aber lang ...

von Thomas M. (Firma: https://img.favpng.com/23/21/3) (thomasmopunkt)


Lesenswert?

leider keine hilfreiche Antwort aber witzig ;-)
http://www.toodarkpark.org/computers/humor/shoot-self-in-foot.html

Pascal und Delphi gefallen mir :-)

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

> spielfeld[0]=" 012345678";

damit überschreibt du dir deinen Zeiger den du vorher per malloc geholt 
hast. Jetzt zeigt spielfeld[0] auf eine Datenbereich den du nicht ändern 
darfst. Damit stützt das Programm beim ersten schreibenden Zugriff auf 
spielfeld[0][x] ab.


Bitte fang noch mal neu mit dem Programm an, das ganze mit dem Zeiger 
auf Zeiger ist nicht sehr gut und viel zu kompliziert.

von Gerd E. (robberknight)


Lesenswert?

Bei dem Programmierstil ist es kein Wunder daß Du da irgendwo einen 
Speicherzugriffsfehler drin hast und ihn nicht selbst in wenigen Minuten 
finden kannst:

- Einrückungen wie Kraut & Rüben
- Leerzeilen nach Lust & Laune
- Kein einziger Kommentar
- Mal #defines für die Speichergrößen, mal "for(j=2;j<7;j+=2)"
- Wackelige Speicherstruktur mit dem "char **spielfeld". Hier würde ich 
z.B. stattdessen ein struct empfehlen
- malloc ohne free
- keine Prüfung des Rückgabewerts von malloc (könnte auch NULL sein...)

Auch wenn Du den konkreten Fehler irgendwann findest, ist das Programm 
noch meilenweit von robust, wartbar und leicht verständlich entfernt. Es 
lohnt sich, auch schon bei vergleichsweise überschaubaren Programmen an 
sauberem Programmierstil zu arbeiten - dann geht das einem ins Blut über 
und man macht es bei komplexeren Programmen gleich von Anfang an 
richtig.

von Pfui (Gast)


Lesenswert?

Das Thema malloc und Konsorten hatten wir doch vor ein paar Tagen 
schonmal.

Das Problem ist, dass Du ein Programm anfängst, dass recht umfangreich 
ist, ohne die Grundlagen von Zeigern und Arrays verstanden zu haben.

Das solltest Du erstmal gründlich durcharbeiten auch wenn es nicht 
sonderlich unterhaltsam ist.

Dein Code ist in der Tat lang. Deswegen steht über dem Formular für neue 
Beträge auch: "Längeren Sourcecode nicht im Text einfügen, sondern als 
Dateianhang"

Ich helfe gerne, auch bei verwickelten Problemen, aber eine Ansammlung 
von wiederholten Anfängerfehlern, mal abgesehen von der 
grottenschlechten Einrückung, ist meiner Meinung nach so leicht 
vermeidbar, dass die Präsentation solcher schon ganz leicht in die 
Richtung einer Unverschämtheit geht.

Also: Jetzt reiß Dich mal am Riemen und mach das richtig.

von Pfui (Gast)


Lesenswert?

Ausserdem ist mir auch völlig schleierhaft, warum diese Herumgeraffel 
mit Defines nötig ist.

#define GROESSE_FELD 4
#define DIM_ZEILE (GROESSE_FELD * 2+2)
#define DIM_SPALTE (GROESSE_FELD * 2+2)


Die größe eines Sudoku-Feldes ist immer gleich.

Konstanten haben zweckmäßigerweise sowohl durch den Namen als auch durch 
ihren Wert, einen sinnvollen Zusammenhang zur Anwendung. Das ist hier 
nicht der Fall.

Das bedeutet aber auch, das ein malloc völlig überflüssig ist.

An sich ist das, wenn es richtig gemacht wird auch nicht schlimm, aber 
diese Kombination aus unzweckmäßigem Code und dann noch haufenweise 
Trivialfehlern ist doch ein wenig ärgerlich.

Deswegen fängt man eigentlich mit kleinen Programmen an bis man 
Trivialfehler weg hat und man liest mal ein paar Absätze über einige 
Basis-Algorithmen bis man in der Lage ist, ein wenig mehr vom 
Großen-Ganzen zu erkennen.

von Pfui (Gast)


Lesenswert?

Davon mal abgesehen benötigt der Anfänger (in der überwiegenden Zahl der 
Fälle) auch kein Goto.

Es ist wohl wahr, dass das in einigen Fällen Code spart, aber für den 
Anfänger ist es viel lehrreicher, das im Fall der Fälle zu vermeiden und 
zu sehen wie der Code dann aussieht, wenn die anderen Kontrollstrukturen 
wirklich voll ausgenutzt werden. In Deinem Fall z.B. ist ein if-else if 
oft völlig ausreichend und auch offensichtlicher.

Da Goto aber ohnehin relativ selten wirklich Code spart und unnötig ist, 
ist es auch eine gute Daumenregel - jedenfalls für Anfänger.

von guest (Gast)


Lesenswert?

guest schrieb:
> Außerdem passt Dein Funktionsparameter "char **spielfeld" nicht wirklich
> zu den Zugriffen darauf (z.B. "spielfeld[i][j]"). Addressen von
> Zeichenketten zu vergleichen macht nur sehr selten wirklich Sinn.

OK, das stimmt so natürlich nicht. Die passen schon zusammmen.
Allerdings hat Dein Feld nur 10 Elemmente, Du greifst aber in 
'sodokuCheck' auf 13 zu.

von Daniel S. (dani2304)


Lesenswert?

Ja Problem ist, dass ist von der Aufgabe so vorgegeben ... Also mit 
**spielfeld und #define

von Daniel S. (dani2304)


Lesenswert?

guest schrieb:
> guest schrieb:
>> Außerdem passt Dein Funktionsparameter "char **spielfeld" nicht wirklich
>> zu den Zugriffen darauf (z.B. "spielfeld[i][j]"). Addressen von
>> Zeichenketten zu vergleichen macht nur sehr selten wirklich Sinn.
>
> OK, das stimmt so natürlich nicht. Die passen schon zusammmen.
> Allerdings hat Dein Feld nur 10 Elemmente, Du greifst aber in
> 'sodokuCheck' auf 13 zu.

Inwiefern greife ich auf 13 zu?

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Mit diesem Code Beitrag "Re: Programmabsturz - Fehler unbekannt" 
gibt Valgrind folgende auskunft:
1
$ valgrind --leak-check=full -v ./main
2
==11136== Memcheck, a memory error detector
3
==11136== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
4
==11136== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
5
==11136== Command: ./main
6
==11136== 
7
...
8
==11136== Invalid write of size 1
9
==11136==    at 0x4007A9: spielGeruest (in /home/bloody/main)
10
==11136==    by 0x4011EE: main (in /home/bloody/main)
11
==11136==  Address 0x51d512a is 0 bytes after a block of size 10 alloc'd
12
==11136==    at 0x4C2AB8D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
13
==11136==    by 0x4011CB: main (in /home/bloody/main)
14
==11136== 
15
--11136-- REDIR: 0x4ec14d0 (libc.so.6:strchrnul) redirected to 0x4c31c60 (strchrnul)
16
--11136-- REDIR: 0x4eb7420 (libc.so.6:strlen) redirected to 0x4c2dba0 (strlen)
17
--11136-- REDIR: 0x4ebac40 (libc.so.6:__GI_mempcpy) redirected to 0x4c31e60 (__GI_mempcpy)
18
 012345678
19
==11136== Invalid read of size 1
20
==11136==    at 0x4C2DBB4: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
21
==11136==    by 0x4E7FE22: vfprintf (in /usr/lib/libc-2.24.so)
22
==11136==    by 0x4E86278: printf (in /usr/lib/libc-2.24.so)
23
==11136==    by 0x400810: ausgabeSpielfeld (in /home/bloody/main)
24
==11136==    by 0x4011F7: main (in /home/bloody/main)
25
==11136==  Address 0x51d512a is 0 bytes after a block of size 10 alloc'd
26
==11136==    at 0x4C2AB8D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
27
==11136==    by 0x4011CB: main (in /home/bloody/main)
28
==11136== 
29
...
30
==11136== Invalid read of size 8
31
==11136==    at 0x401015: sodokuCheck (in /home/bloody/main)
32
==11136==    by 0x40121B: main (in /home/bloody/main)
33
==11136==  Address 0x51d5090 is 0 bytes after a block of size 80 alloc'd
34
==11136==    at 0x4C2AB8D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
35
==11136==    by 0x4011AA: main (in /home/bloody/main)
36
==11136== 
37
==11136== Invalid read of size 1
38
==11136==    at 0x401019: sodokuCheck (in /home/bloody/main)
39
==11136==    by 0x40121B: main (in /home/bloody/main)
40
==11136==  Address 0x2 is not stack'd, malloc'd or (recently) free'd
41
==11136== 
42
==11136== 
43
==11136== Process terminating with default action of signal 11 (SIGSEGV): dumping core
44
==11136==  Access not within mapped region at address 0x2
45
==11136==    at 0x401019: sodokuCheck (in /home/bloody/main)
46
==11136==    by 0x40121B: main (in /home/bloody/main)
47
==11136==  If you believe this happened as a result of a stack
48
==11136==  overflow in your program's main thread (unlikely but
49
==11136==  possible), you can try to increase the size of the
50
==11136==  main thread stack using the --main-stacksize= flag.
51
==11136==  The main thread stack size used in this run was 8388608.
52
2,2Erste4,2--11136-- REDIR: 0x4eb22f0 (libc.so.6:free) redirected to 0x4c2bccc (free)
53
==11136== 
54
==11136== HEAP SUMMARY:
55
==11136==     in use at exit: 180 bytes in 11 blocks
56
==11136==   total heap usage: 13 allocs, 2 frees, 2,228 bytes allocated
57
==11136== 
58
==11136== Searching for pointers to 11 not-freed blocks
59
==11136== Checked 65,336 bytes
60
==11136== 
61
==11136== 10 bytes in 1 blocks are definitely lost in loss record 1 of 3
62
==11136==    at 0x4C2AB8D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
63
==11136==    by 0x4011CB: main (in /home/bloody/main)
64
==11136== 
65
==11136== LEAK SUMMARY:
66
==11136==    definitely lost: 10 bytes in 1 blocks
67
==11136==    indirectly lost: 0 bytes in 0 blocks
68
==11136==      possibly lost: 0 bytes in 0 blocks
69
==11136==    still reachable: 170 bytes in 10 blocks
70
==11136==         suppressed: 0 bytes in 0 blocks
71
==11136== Reachable blocks (those to which a pointer was found) are not shown.
72
==11136== To see them, rerun with: --leak-check=full --show-leak-kinds=all
73
==11136== 
74
==11136== ERROR SUMMARY: 39 errors from 5 contexts (suppressed: 0 from 0)
75
==11136== 
76
==11136== 1 errors in context 1 of 5:
77
==11136== Invalid read of size 1
78
==11136==    at 0x401019: sodokuCheck (in /home/bloody/main)
79
==11136==    by 0x40121B: main (in /home/bloody/main)
80
==11136==  Address 0x2 is not stack'd, malloc'd or (recently) free'd
81
==11136== 
82
==11136== 
83
==11136== 1 errors in context 2 of 5:
84
==11136== Invalid read of size 8
85
==11136==    at 0x401015: sodokuCheck (in /home/bloody/main)
86
==11136==    by 0x40121B: main (in /home/bloody/main)
87
==11136==  Address 0x51d5090 is 0 bytes after a block of size 80 alloc'd
88
==11136==    at 0x4C2AB8D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
89
==11136==    by 0x4011AA: main (in /home/bloody/main)
90
==11136== 
91
==11136== 
92
==11136== 18 errors in context 3 of 5:
93
==11136== Invalid read of size 1
94
==11136==    at 0x4C2DBB4: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
95
==11136==    by 0x4E7FE22: vfprintf (in /usr/lib/libc-2.24.so)
96
==11136==    by 0x4E86278: printf (in /usr/lib/libc-2.24.so)
97
==11136==    by 0x400810: ausgabeSpielfeld (in /home/bloody/main)
98
==11136==    by 0x4011F7: main (in /home/bloody/main)
99
==11136==  Address 0x51d512a is 0 bytes after a block of size 10 alloc'd
100
==11136==    at 0x4C2AB8D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
101
==11136==    by 0x4011CB: main (in /home/bloody/main)
102
==11136== 
103
==11136== 
104
==11136== 18 errors in context 4 of 5:
105
==11136== Invalid write of size 1
106
==11136==    at 0x4007A9: spielGeruest (in /home/bloody/main)
107
==11136==    by 0x4011EE: main (in /home/bloody/main)
108
==11136==  Address 0x51d512a is 0 bytes after a block of size 10 alloc'd
109
==11136==    at 0x4C2AB8D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
110
==11136==    by 0x4011CB: main (in /home/bloody/main)
111
==11136== 
112
==11136== ERROR SUMMARY: 39 errors from 5 contexts (suppressed: 0 from 0)
113
Speicherzugriffsfehler (Speicherabzug geschrieben)

clang mit -fsanitize=address liefert:
1
$ ./main
2
=================================================================
3
==11075==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000efda at pc 0x000000500433 bp 0x7ffee7053580 sp 0x7ffee7053578
4
WRITE of size 1 at 0x60200000efda thread T0
5
    #0 0x500432 in spielGeruest (/home/bloody/main+0x500432)
6
    #1 0x502c6e in main (/home/bloody/main+0x502c6e)
7
    #2 0x7fb3ac765290 in __libc_start_main (/usr/lib/libc.so.6+0x20290)
8
    #3 0x4186e9 in _start (/home/bloody/main+0x4186e9)
9
10
0x60200000efda is located 0 bytes to the right of 10-byte region [0x60200000efd0,0x60200000efda)
11
allocated by thread T0 here:
12
    #0 0x4c7ff8 in __interceptor_malloc (/home/bloody/main+0x4c7ff8)
13
    #1 0x502c1b in main (/home/bloody/main+0x502c1b)
14
    #2 0x7fb3ac765290 in __libc_start_main (/usr/lib/libc.so.6+0x20290)
15
16
SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/bloody/main+0x500432) in spielGeruest
17
Shadow bytes around the buggy address:
18
  0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
19
  0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
20
  0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
21
  0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa 00 02 fa fa 00 02
22
  0x0c047fff9de0: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
23
=>0x0c047fff9df0: fa fa 00 02 fa fa 00 02 fa fa 00[02]fa fa 00 02
24
  0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
25
  0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
26
  0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
27
  0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
28
  0x0c047fff9e40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
29
Shadow byte legend (one shadow byte represents 8 application bytes):
30
  Addressable:           00
31
  Partially addressable: 01 02 03 04 05 06 07 
32
  Heap left redzone:       fa
33
  Heap right redzone:      fb
34
  Freed heap region:       fd
35
  Stack left redzone:      f1
36
  Stack mid redzone:       f2
37
  Stack right redzone:     f3
38
  Stack partial redzone:   f4
39
  Stack after return:      f5
40
  Stack use after scope:   f8
41
  Global redzone:          f9
42
  Global init order:       f6
43
  Poisoned by user:        f7
44
  Container overflow:      fc
45
  Array cookie:            ac
46
  Intra object redzone:    bb
47
  ASan internal:           fe
48
  Left alloca redzone:     ca
49
  Right alloca redzone:    cb
50
==11075==ABORTING

Und weil es soviel spass macht lassen wir auch noch splint ueber den 
Code laufen:
1
$ splint sudoko.c 
2
Splint 3.1.2 --- 23 Apr 2014
3
4
sudoko.c: (in function spielGeruest)
5
sudoko.c:10:1: Observer storage assigned to unqualified reference:
6
                  spielfeld[0] = " 012345678"
7
  Observer storage is transferred to a non-observer reference. (Use
8
  -observertrans to inhibit warning)
9
   sudoko.c:10:14: Storage becomes observer
10
sudoko.c:23:12: Test expression for if not boolean, type int: (i % 2)
11
  Test expression type is not boolean or int. (Use -predboolint to inhibit
12
  warning)
13
sudoko.c:24:16: Test expression for if not boolean, type int: (j % 2)
14
sudoko.c:25:17: Suspect modification of observer spielfeld[][]:
15
                   spielfeld[i][j] = '|'
16
  Storage declared with observer is possibly modified. Observer storage may not
17
  be modified. (Use -modobserver to inhibit warning)
18
   sudoko.c:10:14: Storage spielfeld[][] becomes observer
19
sudoko.c:28:13: Suspect modification of observer spielfeld[][]:
20
                   spielfeld[i][j] = '-'
21
   sudoko.c:10:14: Storage spielfeld[][] becomes observer
22
sudoko.c:33:16: Test expression for if not boolean, type int: (j % 2)
23
sudoko.c:34:17: Suspect modification of observer spielfeld[][]:
24
                   spielfeld[i][j] = '|'
25
   sudoko.c:10:14: Storage spielfeld[][] becomes observer
26
sudoko.c:37:17: Suspect modification of observer spielfeld[][]:
27
                   spielfeld[i][j] = 'x'
28
   sudoko.c:10:14: Storage spielfeld[][] becomes observer
29
sudoko.c:40:9: Suspect modification of observer spielfeld[][]:
30
                  spielfeld[i][j + 2] = '\0'
31
   sudoko.c:10:14: Storage spielfeld[][] becomes observer
32
sudoko.c: (in function sodokuVorlage)
33
sudoko.c:64:17: Return value (type int) ignored: scanf("%c", &spi...
34
  Result returned by function call is not used. If this is intended, can cast
35
  result to (void) to eliminate message. (Use -retvalint to inhibit warning)
36
sudoko.c:65:17: Return value (type int) ignored: fflush(stdin)
37
sudoko.c:69:17: Return value (type int) ignored: scanf("%c", &spi...
38
sudoko.c:70:17: Return value (type int) ignored: fflush(stdin)
39
sudoko.c:66:23: Suspected infinite loop.  No value used in loop test (i,
40
    spielfeld, j, spielfeld[], spielfeld[][]) is modified by test or loop body.
41
  This appears to be an infinite loop. Nothing in the body of the loop or the
42
  loop test modifies the value of the loop test. Perhaps the specification of a
43
  function called in the loop body is missing a modification. (Use -infloops to
44
  inhibit warning)
45
sudoko.c:75:17: Return value (type int) ignored: fflush(stdin)
46
sudoko.c:56:18: Variable x declared but not used
47
  A variable is declared but never used. Use /*@unused@*/ in front of
48
  declaration to suppress message. (Use -varuse to inhibit warning)
49
sudoko.c:56:22: Variable y declared but not used
50
sudoko.c: (in function sodokuStart)
51
sudoko.c:102:5: Return value (type int) ignored: scanf("%i %i", &...
52
sudoko.c:103:5: Return value (type int) ignored: fflush(stdin)
53
sudoko.c:109:9: Return value (type int) ignored: scanf("%i %i", &...
54
sudoko.c:112:9: Return value (type int) ignored: fflush(stdin)
55
sudoko.c:115:8: Value x[] used before definition
56
  An rvalue is used that may not be initialized to a value on some execution
57
  path. (Use -usedef to inhibit warning)
58
sudoko.c:115:19: Value y[] used before definition
59
sudoko.c:120:9: Return value (type int) ignored: scanf("%i %i", &...
60
sudoko.c:123:9: Return value (type int) ignored: fflush(stdin)
61
sudoko.c:126:5: Return value (type int) ignored: scanf("%c", &spi...
62
sudoko.c:127:5: Return value (type int) ignored: fflush(stdin)
63
sudoko.c:130:9: Return value (type int) ignored: scanf("%c", &spi...
64
sudoko.c:131:9: Return value (type int) ignored: fflush(stdin)
65
sudoko.c:128:11: Suspected infinite loop.  No value used in loop test (a,
66
    spielfeld, b, spielfeld[], spielfeld[][]) is modified by test or loop body.
67
sudoko.c: (in function main)
68
sudoko.c:185:9: Index of possibly null pointer Feld: Feld
69
  A possibly null pointer is dereferenced.  Value is either the result of a
70
  function which may return null (in which case, code should check it is not
71
  null), or a global, parameter or structure field declared with the null
72
  qualifier. (Use -nullderef to inhibit warning)
73
   sudoko.c:183:10: Storage Feld may become null
74
sudoko.c:187:14: Possibly null storage Feld[] derivable from parameter
75
                    spielGeruest (Feld)
76
  A possibly null pointer is reachable from a parameter or global variable that
77
  is not declared using a /*@null@*/ annotation. (Use -nullstate to inhibit
78
  warning)
79
   sudoko.c:185:19: Storage Feld[] may become null
80
sudoko.c:187:14: Passed storage Feld not completely defined (*(Feld[]) is
81
                    undefined): spielGeruest (Feld)
82
  Storage derivable from a parameter, return value or global is not defined.
83
  Use /*@out@*/ to denote passed or returned storage which need not be defined.
84
  (Use -compdef to inhibit warning)
85
   sudoko.c:185:9: Storage *(Feld[]) allocated
86
sudoko.c:188:18: Passed storage Feld not completely defined (*(Feld[]) is
87
                    undefined): ausgabeSpielfeld (Feld)
88
   sudoko.c:185:9: Storage *(Feld[]) allocated
89
sudoko.c:189:15: Passed storage Feld not completely defined (*(Feld[]) is
90
                    undefined): sodokuVorlage (Feld)
91
   sudoko.c:185:9: Storage *(Feld[]) allocated
92
sudoko.c:190:18: Passed storage Feld not completely defined (*(Feld[]) is
93
                    undefined): ausgabeSpielfeld (Feld)
94
   sudoko.c:185:9: Storage *(Feld[]) allocated
95
sudoko.c:191:13: Passed storage Feld not completely defined (*(Feld[]) is
96
                    undefined): sodokuStart (Feld)
97
   sudoko.c:185:9: Storage *(Feld[]) allocated
98
sudoko.c:192:13: Passed storage Feld not completely defined (*(Feld[]) is
99
                    undefined): sodokuCheck (Feld)
100
   sudoko.c:185:9: Storage *(Feld[]) allocated
101
sudoko.c:193:10: Fresh storage Feld not released before return
102
  A memory leak has been detected. Storage allocated locally is not released
103
  before the last reference to it is lost. (Use -mustfreefresh to inhibit
104
  warning)
105
   sudoko.c:183:5: Fresh storage Feld created
106
sudoko.c:8:6: Function exported but not used outside sudoko: spielGeruest
107
  A declaration is exported, but not used outside this module. Declaration can
108
  use static qualifier. (Use -exportlocal to inhibit warning)
109
   sudoko.c:43:1: Definition of spielGeruest
110
sudoko.c:48:6: Function exported but not used outside sudoko: ausgabeSpielfeld
111
   sudoko.c:53:1: Definition of ausgabeSpielfeld
112
sudoko.c:55:6: Function exported but not used outside sudoko: sodokuVorlage
113
   sudoko.c:80:1: Definition of sodokuVorlage
114
sudoko.c:82:10: Function exported but not used outside sudoko: sodokuStart
115
   sudoko.c:148:5: Definition of sodokuStart
116
sudoko.c:150:10: Function exported but not used outside sudoko: sodokuCheck
117
   sudoko.c:177:5: Definition of sodokuCheck
118
119
Finished checking --- 44 code warnings

Das sollten erstmal genug Hinweise auf moegliche Probleme sein.

von Pandur S. (jetztnicht)


Lesenswert?

Debugging ist keine eigene Disziplin, sondern Teil der Programmierung. 
Ein programm sollte immer so aufgebaut sein, dass es Debugging 
unterstuetzt.

Da es sich hier um ein PC Programm handelt kann man komfortable 
Singel-steppen. Und sich bei jedem Schritt die Variablen anschauen, und 
mit den eigenen Vorstellungen vergleichen.

von Peter II (Gast)


Lesenswert?

Oh D. schrieb:
> Da es sich hier um ein PC Programm handelt kann man komfortable
> Singel-steppen. Und sich bei jedem Schritt die Variablen anschauen, und
> mit den eigenen Vorstellungen vergleichen.

nur hilft das hier nicht wirklich weiter. Er macht einen schreibenden 
Zugriff auf Read-Only Daten. Im Debugger sieht er das was er erwartet.

von Pandur S. (jetztnicht)


Lesenswert?

> Er macht einen schreibenden Zugriff auf Read-Only Daten.

Da meckert schon mein Compiler. Und falls nicht, wuerde ja beim 
naechsten Durchgang das Falsche drin stehen.

von Sudoku (Gast)


Lesenswert?

Und: es heißt Sudoku, nicht Sodoku!

von Peter II (Gast)


Lesenswert?

Oh D. schrieb:
>> Er macht einen schreibenden Zugriff auf Read-Only Daten.
>
> Da meckert schon mein Compiler.

nein macht er nicht, das kann er nicht überblicken.


> Und falls nicht, wuerde ja beim
> naechsten Durchgang das Falsche drin stehen.
stimmt auch nicht, das Programm stürzt ab, dann gibt es keinen nächsten 
Durchgang.

von Daniel S. (dani2304)


Lesenswert?

Okay vielen Dank schonmal. Muss da auf jeden Fall noch viel Arbeit 
reinstecken :) Aber werde zuerst versuchen das Thema mit Pointern etc. 
besser zu verstehen.

von guest (Gast)


Lesenswert?

Daniel S. schrieb:
>> OK, das stimmt so natürlich nicht. Die passen schon zusammmen.
>> Allerdings hat Dein Feld nur 10 Elemmente, Du greifst aber in
>> 'sodokuCheck' auf 13 zu.
>
> Inwiefern greife ich auf 13 zu?

Schau Dir die Schleife mit dem 'i' an, überleg wie groß 'i' wird und was 
dann innerhalb der Schleife bei 'i+6' passiert.

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.