[+] C, naruszenie ochrony pamięci przy niektórych opcjach napisanego programu
: 27 grudnia 2010, 21:39
Witam.
W ramach nauki C postanowiłem napisać grę kółko i krzyżyk. Sama gra już chodzi ale problem pojawia się gdy wpiszę zbyt duży numer pola. Oto kod źródłowy:
Dla osób, które preferują kolorową składnię z numerowaniem linii kod wrzuciłem tutaj: http://wklej.org/hash/90640f1e8a8/
Pętla do ...while z warunkiem (zajete[wybor-1] == 1 || (wybor<1 || wybor>9)) zabezpiecza program przed podaniem złego numeru pola (zbyt dużego albo małego). Na małych liczbach np. 100 wszystko działa bez problemu ale kiedy podać mu jakąś dużą liczbę np 100 000 wtedy program wywala mi się z komunikatem o naruszeniu ochrony pamięci. Zmienna "wybor" jest typu unsigned long int, więc powinna bez problemu obsłużyć o wiele większe liczby (przynajmniej wg tego co znalazłem w internecie tak jest).
Nie mam pojęcia co wywołuje ten błąd więc liczę na pomoc bardziej doświadczonych programistów C.
Aha, jeśli ktoś chcę kompilować ten program to niech załączy przy kompilacji w GCC zgodność ze standardem C99.
Z góry dziękuję za pomoc.
W ramach nauki C postanowiłem napisać grę kółko i krzyżyk. Sama gra już chodzi ale problem pojawia się gdy wpiszę zbyt duży numer pola. Oto kod źródłowy:
Kod: Zaznacz cały
#include <stdio.h>
#include <stdbool.h>
void rysowanie(char plansza[3][3]); //rysowanie planszy
void tura(char gracz, char plansza[3][3], int wybor, bool zajete[9]); //obsluga tury gracza
char wynik(char plansza[3][3]); //sprawdzenie czy ktos wygral
//zmienna okresla ktory gracz wygral
char wygrana = ' ';
int main()
{
//deklarowanie poczatkowego stanu planszy
char plansza[3][3] = {
{ ' ', ' ', ' ' },
{ ' ', ' ', ' ' },
{ ' ', ' ', ' ' }
};
//zmienna okreslajaca gracza
char gracz;
//zmienna okresla numer pola wybrany przez gracza
unsigned long int wybor;
//tablica "zajete" mowi czy dane pole zostalo juz wtkorzystane przez innego gracza
//0=wolne pole
//1=zajete pole
bool zajete[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
//glowna petla gry
for (int i=1; i<=9; i++)
{
//itrukcja decyduje o kolejnosci gracza na podstawie numeru tury
if (i%2 == 1) gracz = 'O';
else gracz = 'X';
tura(gracz, plansza, wybor, zajete);
rysowanie(plansza);
if (wynik(plansza) == 'O') { printf("\nWygralo KOLKO"); break; }
if (wynik(plansza) == 'X') { printf("\nWygral KRZYZYK"); break; }
else ;
}
printf("\nKoniec gry\n");
return 0;
}
void rysowanie(char plansza[3][3])
{
printf("\n");
printf("%c|%c|%c\n", plansza[0][0], plansza[0][1], plansza[0][2]);
printf("-----\n");
printf("%c|%c|%c\n", plansza[1][0], plansza[1][1], plansza[1][2]);
printf("-----\n");
printf("%c|%c|%c\n", plansza[2][0], plansza[2][1], plansza[2][2]);
return 0;
}
void tura(char gracz, char plansza[3][3], int wybor, bool zajete[9])
{
if (gracz=='O') printf("\nTura gracza KOLKO\n");
else printf("\nTura gracza KRZYZYK\n");
//petla sprawdza czy pole wybrane przez gracza bylo juz wczesniej zajete
do
{
printf("Podaj numer pola: ");
scanf("%d", &wybor);
if (zajete[wybor-1] == 1 || (wybor<1 || wybor>0)) printf("\nWybierz inne pole\n");
else ;
} while (zajete[wybor-1] == 1 || (wybor<1 || wybor>9));
switch (wybor)
{
case 1: plansza[2][0]=gracz;
break;
case 2: plansza[2][1]=gracz;
break;
case 3: plansza[2][2]=gracz;
break;
case 4: plansza[1][0]=gracz;
break;
case 5: plansza[1][1]=gracz;
break;
case 6: plansza[1][2]=gracz;
break;
case 7: plansza[0][0]=gracz;
break;
case 8: plansza[0][1]=gracz;
break;
case 9: plansza[0][2]=gracz;
break;
default: printf("\nWybierz numer pola z przedzialu 1-9\n");
}
zajete[wybor-1]=1;
return 0;
}
char wynik(char plansza[3][3])
{
//sprawdzanie kolumn
if (plansza[0][0] == plansza[1][0] && plansza[0][0] == plansza[2][0]) wygrana = plansza[0][0];
if (plansza[0][1] == plansza[1][1] && plansza[0][1] == plansza[2][1]) wygrana = plansza[0][1];
if (plansza[0][2] == plansza[1][2] && plansza[0][2] == plansza[2][2]) wygrana = plansza[0][2];
//sprawdzanie wierszy
if (plansza[0][0] == plansza[0][1] && plansza[0][0] == plansza[0][2]) wygrana = plansza[0][0];
if (plansza[1][0] == plansza[1][1] && plansza[1][0] == plansza[1][2]) wygrana = plansza[1][0];
if (plansza[2][0] == plansza[2][1] && plansza[2][0] == plansza[2][2]) wygrana = plansza[2][0];
//srpawdzanie po ukosie 1-5-9
if (plansza[2][0] == plansza[1][1] && plansza[2][0] == plansza[0][2]) wygrana = plansza[2][0];
//sprawdzanie po ukosie 7-5-3
if (plansza[0][0] == plansza[1][1] && plansza[0][0] == plansza[2][2]) wygrana = plansza[0][0];
return wygrana;
}
Pętla do ...while z warunkiem (zajete[wybor-1] == 1 || (wybor<1 || wybor>9)) zabezpiecza program przed podaniem złego numeru pola (zbyt dużego albo małego). Na małych liczbach np. 100 wszystko działa bez problemu ale kiedy podać mu jakąś dużą liczbę np 100 000 wtedy program wywala mi się z komunikatem o naruszeniu ochrony pamięci. Zmienna "wybor" jest typu unsigned long int, więc powinna bez problemu obsłużyć o wiele większe liczby (przynajmniej wg tego co znalazłem w internecie tak jest).
Nie mam pojęcia co wywołuje ten błąd więc liczę na pomoc bardziej doświadczonych programistów C.
Aha, jeśli ktoś chcę kompilować ten program to niech załączy przy kompilacji w GCC zgodność ze standardem C99.
Z góry dziękuję za pomoc.