Strona 1 z 1

{C++} terminal -> segmentation fault (core dumped)

: 04 wrz 2007, 17:26
autor: ekonovember
witam problem jest następujący mam napisany prosty kontener w C++ (klasa szablonowa)
jest to część innej klasy a ta z kolei jest częścią innej (nie o to tutaj chodzi) w każdym razie:
alokuje nowy ciągły obszar pamięci na kontener (po dodaniu nowego elementu)
przepisuje całość do tymczasowego obszaru
zwalniam obszar kontenera (tego glownego) //tu jest problem
alokuje nowy obszar (zwiększony)
przepisuje z tymczasowego do nowego
zwalniam tymczasowy //tu jest problem

no właśnie to jest chyba standardzik i to oczywiscie powinno działać na systemach unixowych bez problemu tak samo jak działa na windzie (sprawdzalem oczywiscie) ALE pomimo tego że kompiluje sie bez warningów (notabene na tym samym kompilatorze bo pod g++ [dev, anjuta]) to proba uruchomienia programu wywala komunikat o bledzie segmentacji, wywala go tylko kiedy używam sławetnego delete (no ale przecież musze zwalniać pamięć żeby nie było wycieków)

dlatego jeśli ktoś może mi wytłumaczyć dla czego to nie śmiga to bede wdzieczny

: 04 wrz 2007, 19:40
autor: DNADesigNed
Ciężko rozmawiać o problemie natury developerskiej, skoro nie widać kodu. Jeżeli nie chcesz/nie możesz udostępnić kodu, to zaprojektuj coś podobnego (i uproszczonego), żeby zaprezentować omawiany przypadek.

Poza tym nie rozumiem czegoś. Skoro potrzebujesz sobie przepisać dane z jednego kontenera do drugiego, większego, to nie łatwiej Ci po prostu stworzyć drugi obiekt i przepisać wartości z pierwszego bez żadnych obszarów pośrednich?
Coś w tym stylu:
1. Alokacja obszaru pamięci.
2. Alokacja zwiększonego obszaru pamięci.
3. Przepisanie danych między obszarami.
4. Zwolnienie obszaru z kroku 1.

: 04 wrz 2007, 20:40
autor: ekonovember
masz racje kod to podstawa tutaj dwie potrzebne metody:

Kod: Zaznacz cały

template<class typ>
bool eko_dyntab<typ>::powieksz(int o_ile)
{
  typ *tmp;
    try
      {
        tmp= new typ[rozmiar + o_ile];
      }
    catch(...)
      {
        return false;
      }
  for(unsigned int i= 0; i < rozmiar; i++)
    tmp[i]= tab[i];
  delete []tab; //zwalniam stary obszar tu jest problem (tylko na etapie wykonania programu)
  tab= tmp;
  rozmiar+= o_ile;
  return true;
}
template<class typ>
bool eko_dyntab<typ>::dodaj_el(typ co)
{
  if(powieksz(1))
    try
      {
        tab[rozmiar - 1]= co;
      }
    catch(...)
      {
        return false;
      }
  return true;
}
jak widzisz napisane to mam tak jak u Ciebie jakos nie wzrocilem uwagi na te moje punkty z posta wyzej ze niesa identyczne niz w programie, ale jak sam widzisz to nie jest istotne, problem tkwi w samym delete ktory powoduje wywalenie bledu od procka podczas wykonywania programu, oczywiscie jak zakomentuje linijke z delete to smiga bez problemu tylko ze trace bez sensu pamiec a tak oczywiscie byc nie moze.

: 05 wrz 2007, 00:02
autor: DNADesigNed
Wiesz co? Podejrzewam, ze zmienna, którą chcesz modyfikować jest lekko poza zasięgiem metody powieksz. Spróbuj w ten sposób:

Kod: Zaznacz cały

template<class typ>
bool eko_dyntab<typ>::powieksz(typ *tab, int o_ile)
... i dalej tak, jak bylo
To by dużo tłumaczyło, bo segmentation fault występuje dopiero, gdy próbujesz zwolnić pamięć na obszarze nie przydzielnym (czyli de facto usunąć coś, czego nie ma).

: 05 wrz 2007, 09:23
autor: ekonovember
to znaczy może tego nie widać ale nie musze przekazywać wskaznika na tab bo to składowa klasy (bez operatora zasięgu no bo nie potrzeba) ta składowa wygląda tak:
typ *tab;
wiec jak najbardziej moge to potraktowac delete co zreszta potwierdza to ze nia mam zadnego warninga przy kompilacji (i ze ten sam kod smiga pod windowsem) zastanawiem sie natomiast czy to nie jest jakis problem z przydzialem sterty no ale teraz znowu niewiem czy to na poziomie kompilatora czy co mniej prawdopodobne systemu

moze to smieszne ale sprubowalem tez tak:
delete tab; co nie mialo by wiekszego sensu i na widnowsie nie skompilowaloby sie (tzn pod devem) a tutaj jak najbardziej skompiluje sie ale wywala to samo co poprzednio

i oczywiscie nie chodzi tu o to że sie uparlem na swoj kontener zamiast wrzucic tam "vector" (ktory dziala jesli podmienie moj kontener na niego) tylko o to czemu taki blad - śmieszna sprawa :]

: 05 wrz 2007, 10:56
autor: jj ptak
zainteresuj sie valgrindem, on ci pokaze co robisz zle.

: 05 wrz 2007, 11:33
autor: ekonovember
fakt niesamowite narzędzie - problem rozwiązany tak teraz wygląda okienko terminala:

Kod: Zaznacz cały

==10600== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 1)
==10600== malloc/free: in use at exit: 0 bytes in 0 blocks.
==10600== malloc/free: 18 allocs, 18 frees, 356 bytes allocated.
==10600== For counts of detected errors, rerun with: -v
==10600== All heap blocks were freed -- no leaks are possible.
root@eko-komp:/home/eko/programowanie/anjuta/container# ./eko_container a b c d e f g
./eko_container
a
b
c
d
e
f
g
wcześniej:

Kod: Zaznacz cały

root@eko-komp:/home/eko/programowanie/anjuta/container# ./eko_container a b c d e f g
Segmentation Fault (core dumped)
a problem był taki:

Kod: Zaznacz cały

template<class typ>
eko_dyntab<typ>::eko_dyntab()
{
  //tab= new typ;  //tutaj nie bylo zakomentowanej linijki czyli tracilem sizeof(typ) bajtow w konstruktorze
  rozmiar= 0;
}
po zakomentowaniu smiga...

moja refleksja na ten temat - systemy unixowe przydzielaja mala sterte :P nie zwolnie 4 bajtow to juz sie nic nie zmiesci :P

: 05 wrz 2007, 12:55
autor: DNADesigNed
I to właśnie udowadnia, że do rozwiązywania problemów najlepiej widzieć cały kod, a nie tylko jego fragment. Błędy mogą być wszędzie.

: 05 wrz 2007, 13:52
autor: ekonovember
no owszem ale to tak naprawde jest nie tle blad co pewna nieelegancja gubienia kilku bajtow... nie powinno miec to wplywu na dzialanie programu przeciez moge sobie zrobic instrukcje iteracyjna od 0 do 10000 gdzie bede robil wsk= new int; bez najmniejszego delete i do konca dzialania programu powinienem miec zaalokowane 10000 * sizeof(int) bajtow bez (uchwytow do nich) i zero bledow...

no coz dzieki za pomoc :]

: 05 wrz 2007, 13:55
autor: jj ptak
prawda jest taka ze warto czasem przeleciec vangridem i byc pewnym ze nie ma bledow. uczysz sie porzadnie programowac.

: 05 wrz 2007, 14:05
autor: DNADesigNed
Prawda jest taka, że jeżeli nie chcesz się martwić o alokację i zwalnianie pamięci, to przesiądź się na Java'ę. Bajecznie prosty język. :) Przewinąłem się przez C/C++, PHP, Pythona i inne pomniejsze (Pascal, Basic, Assembler ale to ciężko mówić o wygodzie :D) i ten język jest dla mnie najwygodniejszy. Poza tym wszystko tym klepniesz: aplikacja konsolowa - nie ma problemu, aplikacja z GUI - spoko, aplikacja web'owa - nic prostszego. Generalnie piszesz to, co chcesz. Na początku podchodziłem do niej bardzo sceptycznie, ale po dwóch latach to nawet w PHP piszę na modłę Java'y (czyli czysta obiektowość). Naprawdę polecam. :)

: 05 wrz 2007, 15:24
autor: ekonovember
w cpp jest shared_ptr z biblioteki boosta ktory dzieki zliczaniu referencji trzyma obiekt przy zyciu tak glugo dopuki sa na niego referencje jak niema to wywala.

java jak najbardziej ale narazie mnie nie kreci a garbage collector przeraza :D

: 05 wrz 2007, 16:26
autor: DNADesigNed
Czyli taki odpowiednik Garbage Collector'a w Java'ie? :)

: 05 wrz 2007, 16:37
autor: ekonovember
nie taka klasa po ktorej mozna dziedziczyc implementacje zliczania referencji do naszej klasy no i przestac sie martwic o delete, garbage collector to z tego co kojaze z wykladow program ktory smiga w osobnym watku po pamieci i wywala to co nie jest potrzebne (a robi to "kiedy chce") ale generalnie chodzi o to zeby nie martwic sie przydzialem i zwalnianiem (chociaz to jest wolne... podobno sa jeszcze szybsze implementacje ale nie wiem za duzo o tym)

: 05 wrz 2007, 18:40
autor: DNADesigNed
Generalnie rzeczywiście śmiga w osobnym wątku i zwalnia obszary pamięci, do których nie trzymane są referencje. Nie zauważyłem jednak, żeby wolno działał, ale faktycznie działa kiedy chce (nawet jak specjalnie go wywołasz, to nie gwarantuje Ci, że się uruchomi). W każdym razie jest o tyle łatwiej, że nie trzeba się martwić o zarządzanie pamięcią.

: 06 wrz 2007, 11:08
autor: ekonovember
a to juz wogole nie wiedzialem ze mozna go wywolywac (jak by sie zachwywal deterministycznie to by chyba kazdemu bylo wygodniej)

a co do boosta:

Kod: Zaznacz cały

#include <co tam trzeba>
#include <boost/shared_ptr.hpp>

class info
{
  public:
    info()
      {
        std::cout << "konstruktor" << std::endl;
      }
    ~info()
      {
        std::cout << "destruktor" << std::endl;
      }
};

int main()
{
  { //sztucznie zeby pokazac zasieg
    boost::shared_ptr<info> x;
      {
        boost::shared_ptr<info> a (new info);
        x= a;
      } //a tutaj nie ginie bo jest na nie referencja
  } //tutaj ginie x oraz ginie a
}
mniej wiecej cos takiego (podobno jeszcze sie da dziedziczyc sam ten mechanizm jak napisalem wyzej)

: 06 wrz 2007, 11:15
autor: DNADesigNed
No to z tego, co napisałeś wygląda to jak garbage collector dla C++, z tym że wykonuje się od razu, a nie zależnie od humoru. :P

Odp: {C++} terminal -> segmentation fault (core dumped)

: 08 lut 2008, 15:45
autor: said
Czy ktoś może wie jak odwołać sie do zmiennej lokalnej innej funkcji z poziomu funkcji main ?

Odp: {C++} terminal -> segmentation fault (core dumped)

: 08 lut 2008, 16:06
autor: el.pescado
Nie da się.

Odp: {C++} terminal -> segmentation fault (core dumped)

: 12 lis 2008, 01:13
autor: kruk87
Witam, podłącze się pod ten topic bo mam dokładnie ten sam problem z segmentation fault. czy mógłby mi ktos powiedzieć dokładnie gdzie robie błąd (wiem że jest to funkcja push);

Kod: Zaznacz cały

#include <iostream>

//#define _size 5
#define start_size 5







class stos

	{

	public:

	void init(int* dane);
	void push(int* dane, int dana);

	int pop(int* dane);

	void destroy(int* dane);

	void show(int* dane, int szczyt);


	private:

	int Size;

	int *dane;

	int szczyt;

	};

void stos::init(int *dane)
	{
	szczyt=0;
//	dane =(int*) malloc(sizeof(int) * _size);
	dane = new int[start_size];
	Size=start_size;
	}


void stos::destroy(int *dane)
	{ 
	szczyt=0;
	delete [] dane;
	Size=start_size;
	}


void stos::push(int* dane, int dana)
	{
	if(szczyt == Size)
		{
		Size+=start_size;
		int* tmp;
		tmp = new int[Size];
		int i;
		for(i=0; i<Size-start_size; i++)
			{
				tmp[i]=dane[i];
			}
		delete [] dane;
		dane = new int[Size];
		for(i=0; i<Size; i++)
			{
			dane[i]=tmp[i];
			}
		delete [] tmp;
		//realloc(dane, sizeof(int) * Size);
		}
	dane[szczyt]=dana;
	}

int stos::pop(int* dane)
	{
	if(szczyt>0)
		{
		szczyt-=1;
		}
	return dane[szczyt+1];
	
	}

void stos::show(int* dane, int szczyt)
	{
	int i;
	for(i=0; i<szczyt; i++)
		{
		std::cout << dane[i];	
		}
	}



int main()
	{
	return 0;
	}