0xC0000005 przy odczycie z dynamicznej tablicy

0

Witam spotkał się ktoś takim błędem:
"Unhandled exception at 0x104e8dcb in Projekt Poprawa.exe: 0xC0000005: Access violation reading location 0xfeeefeee."

W programie działam na tablicach dynamicznych

0

tak (odpowiedź jest na tyle pełna na ile pozwala pytanie).

0

Wychodzisz poza tablicę albo zwalniasz tablicę 2 razy itd.

0

Tylko, że ten błąd pojawia się nie przy wpisywaniu danych do tablicy, ale gdy chce np. odczytać z niej dane albo zapisać te dane do pliku

0

Funkcja zapisująca:

void zapis_produkt(char *in,Produkt *s,int dlugosc_produkt)			// funkcja zapisująca baze do pliku
{
	ofstream plik(in, ios::out | ios::ate) ;

		
	
	//	plik<<dlugosc_produkt<<endl;	// zapisujemy ilosc produktow jako 1 wartosc w pliku
	for(int i=0 ; i<dlugosc_produkt ; ++i)
	{

				plik<<s[i].numer<<endl;
				plik<<s[i].kategoria<<endl;
				plik<<s[i].nazwa_produktu<<endl;
				plik<<s[i].ilosc<<endl;
				plik<<s[i].cena<<endl;
	}
}

Funkcja wypisująca

void wypisz_produkt(Produkt *s,int rozmiar_produkt)
{
	for(int i=0 ; i<rozmiar_produkt ;)
	{
	 cout<<"Nr."<<s[i].numer<<endl;
	 cout<<"kategoria :         "<<s[i].kategoria<<endl;
	 cout<<"nazwa_produktu :    "<<s[i].nazwa_produktu<<endl;
	 cout<<"dostepna ilosc :    "<<s[i].ilosc<<endl;
	 cout<<"Cena :              "<<s[i].cena<<endl;
	 cout<<"-  -  -  -  -  -  -  -  -  -  -  -  -\n";
 
	i++;
	if(i % 5==0) system("pause"); // wyswietlamy po 5 wpisow i czekamy na klawisz
	}
}

0

No i co z tego? Pokaż jak tworzysz ową tablicę.

0

Pierwsza deklaracja
Produkt *s = new Produkt [dlugosc_produkt];

Druga deklaracja

case '1':
							{
								system("cls");
								int n;
								cout<<"ile produktow chcesz dodac:";
								cin >> n;
								
								if(n>dlugosc_produkt)
								{
									delete[]s;
								
									Produkt *s = new Produkt [n+dlugosc_produkt];
0

if(n>dlugosc_produkt) ? A to niby czemu?
Jeśli mam 10 produktów, chce dodać 1, to wg ciebie nie nalezy tej tablicy powiększyć? o_O

0

Fakt, na początku miałem jeszcze zwiększaną tą tablice przy pierwszej deklaracji.
Po usunięciu warunku dzieje się to samo

0

No to przykro mi ale te skrawki kodu które pokazałeś nie mają jako takich błędów, a z fusów wróżyć trudno.

0

Czemu, za mało, dosyć prosto to wygląda:

 if(n>dlugosc_produkt)
{
  delete[]s;
  Produkt *s = new Produkt [n+dlugosc_produkt];

zwalnia s (to poziom wyżej), potem tworzy nowe lokalne s i pewnie gubi do niego wskaźnik. "Wyższe" s jest usunięte i wskazuje na śmieci, a "niższe" s jest gubione, i leci wyjątek ;).

0

Oto mój kod

#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <time.h>
using namespace std;



struct Produkt
{
	int numer;					//	numer w bazie
	string kategoria;			//	kategoria produktu	
	string nazwa_produktu;		//	nazwa produktu
	int ilosc;					//  ilosc produktow na magazynie
	double cena;				//	cena produktu
};

struct Klient
{
	int numer;					// numer w bazie			
	string login;				// login klienta
	int punkty;					// posiadane punkty

};

struct Pomocnicza
{
	int numer;					//	numer w bazie
	string kategoria;			//	kategoria produktu	
	string nazwa_produktu;		//	nazwa produktu
	int ilosc;					//  ilosc produktow na magazynie
	double cena;				//	cena produktu
};

int rozmiar_produkt(char *in)
{
	string nazwa_produktu , kategoria;
	int numer, ilosc;
	double cena;
	
	ifstream plik(in);
	int rozmiar_produkt = 0;
	
	while(!plik.eof())
	{
		plik>>numer;
		plik>>kategoria;
		plik>>nazwa_produktu;
		plik>>ilosc;
		plik>>cena;
		
		rozmiar_produkt += 1;
	}
	
	plik.close();
	return rozmiar_produkt;
}

int rozmiar_klient(char *in)
{
	string login , imie;
	int numer;
	int punkty;
	
	ifstream plik(in);
	int rozmiar_klient = 0;
	
	while(!plik.eof())
	{
		plik>>numer;
		plik>>login;
		plik>>punkty;
		
		rozmiar_klient += 1;
	}
	
	plik.close();
	return rozmiar_klient;
}

//*************************************************************************
void zpliku_produkt(char *in,Produkt *s,int &dlugosc_produkt)
{
	ifstream plik(in);
	//plik>>dlugosc_produkt;				//pobranie dlugosci bazy produktow
//	cout<<"Ile produktow : " << dlugosc_produkt;
	for(int i=0;i<dlugosc_produkt;++i)
	{
		plik>>s[i].numer;
		plik>>s[i].kategoria;
		plik>>s[i].nazwa_produktu;
		plik>>s[i].ilosc;
		plik>>s[i].cena;
	}
	
}
//******************************************************************************************
void zpliku_klient(char *in,Klient*w,int &dlugosc_klient)
{
	ifstream plik(in);
	//plik>>dlugosc_klient;			//pobranie dlugosci bazy danych klientow
	//cout<<"\nIle Klientow : " << dlugosc_klient<<endl<<endl;
	for(int i=0;i<dlugosc_klient;++i)
	{
		plik>>w[i].numer;
		plik>>w[i].login;
		plik>>w[i].punkty;
	}
	
}
//******************************************************************************************
void wypisz_produkt(Produkt *s,int rozmiar_produkt)
{
	for(int i=0 ; i<rozmiar_produkt ;)
	{
	 cout<<"Nr."<<s[i].numer<<endl;
	 cout<<"kategoria :         "<<s[i].kategoria<<endl;
	 cout<<"nazwa_produktu :    "<<s[i].nazwa_produktu<<endl;
	 cout<<"dostepna ilosc :    "<<s[i].ilosc<<endl;
	 cout<<"Cena :              "<<s[i].cena<<endl;
	 cout<<"-  -  -  -  -  -  -  -  -  -  -  -  -\n";
 
	i++;
	if(i % 5==0) system("pause"); // wyswietlamy po 5 wpisow i czekamy na klawisz
	}
}
//******************************************************************************************
void wypisz_klient(Klient *w,int rozmiar_klient)
{



	for(int i=0 ; i<rozmiar_klient ; )
	{
		cout<<"Nr."<<w[i].numer<<endl;
		cout<<"login :    "<<w[i].login<<endl;
		cout<<"punkty :    "<<w[i].punkty<<endl;
		cout<<"-  -  -  -  -  -  -  -  -  -  -  -  -\n";
		 i++;
	if(i % 5==0) system("pause");
	}
}
//******************************************************************************************
void zapis_produkt(char *in,Produkt *s,int dlugosc_produkt)			// funkcja zapisująca baze do pliku
{
	ofstream plik(in, ios::out | ios::ate) ;

		
	
	//	plik<<dlugosc_produkt<<endl;	// zapisujemy ilosc produktow jako 1 wartosc w pliku
	for(int i=0 ; i<dlugosc_produkt ; ++i)
	{

				plik<<s[i].numer<<endl;
				plik<<s[i].kategoria<<endl;
				plik<<s[i].nazwa_produktu<<endl;
				plik<<s[i].ilosc<<endl;
				plik<<s[i].cena<<endl;
	}
}
//******************************************************************************************

void zapis_klient(char *in,Klient *w,int dlugosc_klient)			// funkcja zapisująca baze do pliku
{
	ofstream plik(in, ios::out | ios::ate) ;
		
//	plik<<dlugosc_klient<<endl;			// zapisujemy ilosc klientow jako 1 wartosc w pliku
	for(int i=0 ; i<dlugosc_klient ; ++i)
	{

				plik<<w[i].numer<<endl;
				plik<<w[i].login<<endl;
				plik<<w[i].punkty<<endl;
				
	}
}

//******************************************************************************************
void dodaj_do_bazy_produkt(Produkt *s,int n, int &dlugosc_produkt)		//funkcja dodająca produkty do bazy
{
	
	for(int i=0;i<n;++i)
	{
		int j=i + dlugosc_produkt; // nowe wpisy dodajemy na koncu bazy
		s[j].numer = j+1;
		cout<<"Dodaj: "<< i+1 <<" produkt:"<<endl;
		cout<<"Podaj kategorie :\n";
		cin>>s[j].kategoria;
		cout<<"Podaj nazwe_produktu:\n";
		cin>>s[j].nazwa_produktu;
		cout<<"Podaj ilosc danego produktu :\n";
		cin>>s[j].ilosc;
		cout<<"Podaj cene Produktu :\n";
		cin>>s[j].cena;
	
	}
	dlugosc_produkt+=n;


}

//*******************************************************************************************
void dodaj_do_bazy_klient(Klient *s,int n, int &dlugosc_klient)		//funkcja dodająca klientów do bazy
{

	for(int i=0;i<n;++i)
	{
		int j=i + dlugosc_klient; // nowe wpisy dodajemy na koncu bazy
		s[j].numer = j+1;
		cout<<"login :\n";
		cin>>s[j].login;
		cout<<"Punkty:\n";
		cin>>s[j].punkty;
		
	}
	dlugosc_klient+=n;
}//******************************************************************************************

// Funkcja sprawdza czy  podany użytkownik figuruje w bazie klientów
int szukaj(Klient *w,int &dlugosc_klient)
{
	int login;
	string szukany_login;
	cout <<" Podaj login: "<<endl;
	cin >> szukany_login;

	int licznik = 0;
	char wybor;
	
	for(int i=0;i<dlugosc_klient;++i)
	{	
		if(w[i].login == szukany_login) 		// sprawdzamy czy dany klient występuje w bazie
		{
			
			cout<<"\t\t-  -  -  -  -  -  -  -  -  -  -  -  -\n\n";
			
			cout<< "\t\tJestes zalogowany jako "<< w[i].login<<endl
			<<"\n\n\t\tTwoja liczba punktow to: "<<w[i].punkty<<endl<<endl;
			cout<<"\t\t-  -  -  -  -  -  -  -  -  -  -  -  -\n\n";
			return w[i].numer;
		
		}
		
		else
		{
			licznik=licznik+1;					//gdy klient niewystępuje w bazie zwiększamy licznik
		
		}
			

	}
	if (licznik!=0) cout <<"Niema takiego klienta\n\n";
	getchar();
	
}
//*******************************************************************************************
int kup(Produkt *s,int &dlugosc_produkt, Klient *w, int &dlugosc_klient, int znaleziony_klient)
{
	int licznik = 0;
	int punkty=0;
	int numer;

	cout<<"Podaj numer: "<<endl;
	cin >> numer;
	
	for(int i=0;i<dlugosc_produkt;++i)
	{
		
		if (s[i].numer==numer)		//sprawdzamy czy dany produkt znajduje się w bazie
		{
			
			s[i].ilosc=s[i].ilosc-1;
			if (s[i].ilosc<0)
			{
				cout<<"\n--------------";
				cout<<"\n-BRAK TOWARU-";
				cout<<"\n--------------"<<endl;
				s[i].ilosc=0;
				
				punkty=0;
			}
			else
			{
				
				cout<<"Nr."<<s[i].numer<<endl;
				cout<<"kategoria :         "<<s[i].kategoria<<endl;
				cout<<"nazwa_produktu :    "<<s[i].nazwa_produktu<<endl;
				cout<<"dostepna ilosc :    "<<s[i].ilosc<<endl;
				cout<<"Cena :              "<<s[i].cena<<endl;
				cout<<"-  -  -  -  -  -  -  -  -  -  -  -  -\n";
			

				punkty=s[i].cena / 10;				//Za każde wydane 10 zł przyznawany jest 1 punkt
				for(int i=0;i<dlugosc_klient;++i)	//klinentowi, ktory kupil produkt przypisujemy punkty
				if (znaleziony_klient==w[i].numer)
				{
				w[i].punkty+=punkty;				//dodajemy punkty do puli punktow posiadanych przez klienta
				}
			}
	//return punkty;
			
		}
		
	}	

return numer;
}
//*******************************************************************************************************
void rabat(Klient *w, Produkt *s, int numer, int znaleziony, int &dlugosc_produkt, int dlugosc_klient)
{
	
	int punkty;
	for(int i=0;i<dlugosc_klient;++i)
	 if (znaleziony==w[i].numer)
	 {	
		punkty=w[i].punkty; 
		/*w[i].punkty=0;
		w[i].numer;
		w[i].login;
		w[i].punkty; /*
	} 

	for(int i=0;i<dlugosc_produkt;++i)
	{
		/*s[i].numer;
		s[i].kategoria;
		s[i].nazwa_produktu;
		s[i].ilosc;
		s[i].cena;*/
			
		if (numer==s[i].numer)
		{
				cout <<"Cena po rabacie : " <<endl;
				cout<<"Nr."					<<s[i].numer<<endl;
				cout<<"kategoria :         "<<s[i].kategoria<<endl;
				cout<<"nazwa_produktu :    "<<s[i].nazwa_produktu<<endl;
				cout<<"dostepna ilosc :    "<<s[i].ilosc<<endl;
				cout<<"Cena :              "<<s[i].cena-punkty<<endl;
				cout<<"-  -  -  -  -  -  -  -  -  -  -  -  -\n";
			
		}
	}
}

//*******************************************************************************************************
int _tmain(int argc, _TCHAR* argv[])
{
	int dlugosc_klient, dlugosc_produkt;	// zmienne przechowywujace wielkosc bazy
	int znaleziony_klient, numer;	
	char * klienci = ("klienci.txt");
	char * produkty = ("produkty.txt");
	char znak, login, wybor, kto;
	string login_admin;
	int enter;
	dlugosc_produkt=rozmiar_produkt(produkty)-1;
	dlugosc_klient=rozmiar_klient(klienci)-1;
	Produkt *s = new Produkt [dlugosc_produkt+1];
	Klient *w = new Klient [dlugosc_klient+10];
	zpliku_produkt(produkty, s, dlugosc_produkt);
	zpliku_klient(klienci, w, dlugosc_klient);
	zapis_produkt(produkty, s, dlugosc_produkt);
	zapis_klient(klienci, w, dlugosc_klient);








tu:			// miejsce wyskoku
	
	do 
	{
		system("cls");
		cout << "				WITAMY W SKLEPIE\n\n";						 
		cout<<"		Administrator" 						<< "\t\t\twcisnij - 1\n";
		cout<<"		Klient" 							<< "\t\t\t\twcisnij - 2\n";
		cout<<"                Wyloguj"                 << "\t\t\t\twcisnij - 0\n";                     
		cin >> kto;
		switch (kto)	
		{
			case '1':
			{  
				do
				{	
					//cout<<" Podaj login: ";
					//cin>>login_admin;
					//if (login_admin=="admin")
					//{
						system("cls");
						cout<<"		Dodaj Produkt" 					<< "\t\t\twcisnij - 1\n";
						cout<<"		Dodaj klienta" 	                << "\t\t\twcisnij - 2\n";
						cout<<"		Pokaz Produkty" 					<< "\t\t\twcisnij - 3\n";
						cout<<"		Pokaz klientow" 	                << "\t\t\twcisnij - 4\n";
						cout<<"                Wyloguj"             << "\t\t\t\twcisnij - 0\n";
						cin >> wybor;
						switch (wybor)
						{
							case '1':
							{
								system("cls");
								int n;
								cout<<"ile produktow chcesz dodac:";
								cin >> n;
								int a = n;
								int b = dlugosc_produkt;
								
								
								//	zapis_produkt(produkty, s, dlugosc_produkt);
									delete[]s;
									dlugosc_produkt=rozmiar_produkt(produkty)-1;
									Produkt *s = new Produkt [dlugosc_produkt+n];
									
									zpliku_produkt(produkty, s, dlugosc_produkt);
									//Pomocnicza *p = new Pomocnicza [dlugosc_produkt];
									
								dodaj_do_bazy_produkt(s,n,dlugosc_produkt);
								zapis_produkt(produkty, s, dlugosc_produkt);
								wypisz_produkt(s, dlugosc_produkt);
							
							break;
							}
							case '2':
							{
								system("cls");
								int n;
								cout<<"ilu klientow chcesz dodac:";
								cin >> n;
								dodaj_do_bazy_klient(w,n,dlugosc_klient);
								break;
							}
							case '3':
								{
									wypisz_produkt(s, dlugosc_produkt);
									system("pause");
									break;
								}
							case '4':
								{
									wypisz_klient(w, dlugosc_klient);
									system("pause");
									break;
								}
						}		
					
				}
				while(wybor!='0'); 
				goto tu;			//po skonczeniu petli wyskakujemy do glownego menu			
			}    
			case '2':
			{	
				
				 znaleziony_klient=szukaj(w,dlugosc_klient);
				 
				
				if (znaleziony_klient)
				{
					do
					{
						
						cout<<"		Wypisz produkty" 			<< "\t\twcisnij - 1\n";
						cout<<"		Kup" 	                    << "\t\t\twcisnij - 2\n";
						cout<<"                Wyloguj"			<< "\t\t\twcisnij - 0\n";
						cin >> wybor;
						switch(wybor)
						{
							case '1':
								{
									wypisz_produkt(s, dlugosc_produkt);
								break;
								}
							case '2':
							{
								
								numer=kup(s,dlugosc_produkt,w,dlugosc_klient,znaleziony_klient);
								if (numer>dlugosc_produkt)
								{
									cout<<"Niema takiego produktu\n"<<endl;
								}
								else
								{
								cout<<"Czy chcesz skorzystac z rabatu ?   T/N \n";
								cin >> wybor;
								wybor=toupper(wybor); // funkca zamieniająca małą literę na dużą
			
								if (wybor=='T')
								rabat(w,s,numer,znaleziony_klient,dlugosc_produkt,dlugosc_klient);
							}
						}
					
					}
					}
					while (wybor!='0');
				}
					_sleep(500);  //opóźniamy program o 500 ms
			
				
					}
				
				}
		
		}
		while (kto!='0');
	
	
	zapis_produkt(produkty, s, dlugosc_produkt);
	zapis_klient(klienci, w, dlugosc_klient);
	delete[]s;
	delete[]w;

	
	return 0;
}

0

I co mamy z tą 500-linijkową kobyłą zrobić?
Co wiecej widze tam jakieś goto co jeszcze bardziej zniechęca do babrania się w tym kodzie.
Moje rady?

  1. Przepisz to obiektowo. Zrób odpowiednie klasy i metody tych klas. Przetestuj metody niezależnie, tak zeby każda tworzona klasa działała poprawnie, a potem złóż taki program z tych klas.
  2. Zamiast new i delete, z którymi ewidentnie masz problem, używaj <vector>
  3. Zapomnij o istnieniu goto i główą pętlę programu zrób strukturalnie.
0
klajter napisał(a)

Czemu, za mało, dosyć prosto to wygląda:

if(n>dlugosc_produkt)
{
delete[]s;
Produkt *s = new Produkt [n+dlugosc_produkt];

> 
> zwalnia s (to poziom wyżej), potem tworzy nowe lokalne s i pewnie gubi do niego wskaźnik. "Wyższe" s jest usunięte i wskazuje na śmieci, a "niższe" s jest gubione, i leci wyjątek ;).


w jakim sensie gubie wskźnik?
0

Faktycznie dość ewidentny błąd ;]

 Produkt *s = new Produkt [n+dlugosc_produkt];

Tworzysz tutaj nową zmienną o nazwie s, która "zasłania" twoje stare s. Po wyjściu z tego bloku if() {} ta nowa zmienna s znika, a stara zmienna s jest zwolniona. W ten sposób kolejne zwolnienie s powoduje błąd.
zmień to na:

s = new Produkt [n+dlugosc_produkt];
  • ja nadal podtrzymuje moja poprzednią propozycję ;)
0

Dzięki wielkie za pomoc, wszystko teraz śmiga jak należy, a co do poprawy na obiektowe, to niebardzo już mam na to czas, ale dzięki za rade na pewno by to lepiej wyglądało

1 użytkowników online, w tym zalogowanych: 0, gości: 1