[C] problem z funkcją free()

witam, skompilowałem sobie niżej pokazany kod, program tworzy tablice dynamiczna i następnie przypisuje do niej losowe liczby, program do tej pory działał gdy wpisywałem małe liczby ale gdy wpisałem liczbę 99 przestał działać, zatrzymuje się na etapie tworzenia tablicy dynamicznej. mógłby mi ktoś wyjaśnić co się dzieje lub sprawdzić u siebie ten program?? kompiluje go pod linuxem

#include 

#include 


void czyszczenieEkranu (void);

void losuj (int n, int tablica[]);


int main (void)

{

  int ile;

  // int i;

  int *tablica;


  czyszczenieEkranu ();

  printf ("program losuje n podanych liczb i zapisuje je do tablicy\n");

  printf ("ile liczb chcesz wylosowac ?? n= ");

  scanf ("%d ", &ile);


  tablica = (int *) malloc (ile * sizeof (int));


  losuj (ile, tablica);

  free (tablica);



  //printf("zawartosc tablicy po wyczyszczeniu:\n");

  //for(i = 0; i < ile; i++){

    //printf("%d", tablica[i]);

  //}

  //printf("\n");


  return 0;

}


void czyszczenieEkranu (void)

{

  system ("clear");

}


void losuj (int n, int tablica[])

{

  int i;

  printf ("tablica zawiera miejsca na %d elementow\n", n);

  srand (time (NULL));


  for (i = 0; i < n; i++)

    {

      tablica[i] = rand () % 100;

    }


  printf ("elementy w tablicy:\n");

  for (i = 0; i < n; i++)

    {

      printf ("%d ", tablica[i]);

    }


  printf ("\n");

}

Program wydaje się ok, poza może spacją po %d w scanf, ale to już jak wolisz. Oczywiście po free nie powinieneś odwoływać się pod tablica, więc to co jest zakomentowane, powinno pozostać zakomentowane lub usunięte z kodu.

za komentowany kod miał sprawdzić zawartość tablicy po użyciu funkcji free. czemu więc się zatrzymuje gdy jakąś liczbę wpisuje?? dopóki nie wpisałem w programie liczby 99 było dobrze. za duża liczba była użyta?? przepełnienie sterty?? tablice dynamiczne są przechowywane na stercie.

Po free ta pamięć nie jest już twoja (w sensie: procesu, który ją zaalokował), więc nie możesz się do niej odwoływać. Tzn. możesz, ale jest to błędne.

Nie chodzi Ci o tą spację po %d w scanf? Może przez przypadek ją tam wpisałeś, albo nie wiesz jak działa scanf, ale z tą spacją on oczekuje białych znaków po liczbie, żeby zakończyć wczytywanie należy wcisnąc Ctrl+D w takim przypadku (przynajmniej u mnie, bash)

miałeś rację, była to wina funkcji scanf, dopisałem printf("\n") i działa, przechodzi do nowej lini. gdy używałem free to czyścił tylko pierwszy element tablicy. użyłem free(&tablica_) w celu czyszczenia kazdego elementu w tablicy. program się kompiluje i w trakcie działania na samym końcu podczas sprawdzania zawartości tablicy wyskakuje błąd, dlatego działa program tak jak oczekiwałem, o to kod_

#include 

#include 


void czyszczenieEkranu (void);

void losuj (int n, int tablica[]);


int main (void)

{

  int ile;

  int i;

  int *tablica;


  czyszczenieEkranu ();

  printf ("program losuje n podanych liczb i zapisuje je do tablicy\n");

  printf ("ile liczb chcesz wylosowac ?? n= ");

  scanf ("%d", &ile);

  printf("\n");


  tablica = (int *) malloc (ile * sizeof (int));


  losuj (ile, tablica);


  //czyszczenie tablicy

  for(i = 0; i < ile; i++){

    free(&tablica[i]);

  }



  printf("zawartosc tablicy po wyczyszczeniu:\n");

  for(i = 0; i < ile; i++){

    printf("%d ", tablica[i]);

  }

  printf("\n");


  return 0;

}


void czyszczenieEkranu (void)

{

  system ("clear");

}


void losuj (int n, int tablica[])

{

  int i;

  printf ("tablica zawiera miejsca na %d elementow\n", n);

  srand (time (NULL));


  for (i = 0; i < n; i++)

    {

      tablica[i] = rand () % 100;

    }


  printf ("elementy w tablicy:\n");

  for (i = 0; i < n; i++)

    {

      printf ("%d ", tablica[i]);

    }


  printf ("\n");

}

Źle, źle, źle, źle, bardzo źle. WIdać brak podstwowej wiedzy. free robi to: http://www.cplusplus.com/reference/clib … dlib/free/

Zwalnia pamęć zaalokowaną poprzez malloc / calloc / realloc, należy jej podać to co zwrócił malloc/calloc/realloc.

Tak jak pisałem, po free nie powinieneś się odwoływać do tablica, bo to już nie jest twoja pamięć. Najprościej jak potrafię:

1) robisz pamiec = malloc(LICZBA_BAJTOW) - dostajesz wskaźnik na pamięć, i możesz robić co chcesz z LICZBA_BAJTOW kolejnych bajtów zaczynając od zwróconego wskaźnika.

2) wywołujesz free(pamiec) - to co wcześniej zaalokowałęś już nie jest twoje, możesz dodatkowo zrobic “pamiec = NULL”, żeby nie mieć wskaźnika na pamięc, która nie jest twoja.

wybacz ale podstawową wiedzę mam, po prostu chciałem sprawdzić jak będzie program działał. robiłem tak jak podałeś w tym linku, mnie najbardziej interesowała zawartość tablicy po wykonaniu funkcji free. gdy robiłem tak jak pokazane w tym linku i później po sprawdzeniu zawartości pierwszy element był 0 a pozostałe były dalej w pamięci tablicy, teraz po wykonaniu pętli for i funkcji free(tablica_) a nastepnie tablica = NULL na koncu działania programu wyskakuje blad, czyli program działa tak jak trzeba, odwoluje się do pamieci ktora nie istnieje na koncu programu, mysle ze ty Kolego troche na kreciles_

Ostatni kod, który podałeś wywraca się, bo próbujesz zwolnić pamięc spod adresu, który wcale nie wskazujena pamięć zaalokowaną przez malloc.

to jak powinien wygladac zapis zeby prawidlowo zwolnic pamiec??

Samo main:

int main (void)

{

  int ile;

  int i;

  int *tablica;


  czyszczenieEkranu ();

  printf ("program losuje n podanych liczb i zapisuje je do tablicy\n");

  printf ("ile liczb chcesz wylosowac ?? n= ");

  scanf ("%d", &ile);


  tablica = (int *) malloc (ile * sizeof (int));

  losuj (ile, tablica);

  free(tablica);



  return 0;

}

To jest dobry kod (tzn. taki, który się nie wywraca, który poprawnie alokuje i dealokuje dynamicznie pamięć)

wybacz kolego ale tak robiłem, a mi chodzi o to gdy sobie napisze pętle która sprawdzi zawartość tej tablicy to nadal pokazuje że zawiera elementy, choć teoretycznie nie powinno, wytłumacz mi to

Dodane 21.04.2012 (So) 13:55

#include 

#include 


void czyszczenieEkranu (void);

void losuj (int n, int tablica[]);


int main (void)

{

  int ile;

  int i;

  int *tablica;


  czyszczenieEkranu ();

  printf ("program losuje n podanych liczb i zapisuje je do tablicy\n");

  printf ("ile liczb chcesz wylosowac ?? n= ");

  scanf ("%d", &ile);

  printf("\n");


  tablica = (int *) malloc (ile * sizeof (int));


  losuj (ile, tablica);


  free(tablica);


  printf("zawartosc tablicy po wyczyszczeniu:\n");

  for(i = 0; i < ile; i++){

    printf("%d ", tablica[i]);

  }

  printf("\n");


  return 0;

}


void czyszczenieEkranu (void)

{

  system ("clear");

}


void losuj (int n, int tablica[])

{

  int i;

  printf ("tablica zawiera miejsca na %d elementow\n", n);

  srand (time (NULL));


  for (i = 0; i < n; i++)

    {

      tablica[i] = rand () % 100;

    }


  printf ("elementy w tablicy:\n");

  for (i = 0; i < n; i++)

    {

      printf ("%d ", tablica[i]);

    }


  printf ("\n");

}

To jest ściśle zależne od implementacji w systemie operacyjnym i bibliotece języka C.

Odpowiedź na pytanie, dlaczego zawartość pamięci jest taka sama po free jest bardzo prosta - bo akurat nic innego pod tę pamęć nic nie zapisało, aby ją zmienić.

Odpowiedź na pytanie dlaczego proces się nie wysypał po odczytywaniu pamięci po wykonaniu free jest trudniejsza. Niestety nie wiem jak to jest zaimplementowane na najniższym poziomie, ale domyślam się, że:

  1. malloc poprosił system operacyjny o kawałek pamięci i go dostał

  2. free dało znać temu kawałkowi kodu z biblioteki C, który zarządza pamięcią dynamczną, że wcześniej zaalokowana pamięć nie jest już potrzebna - i tyle, tzn. pamięć nie została w żaden sposób zabrana procesowi - stąd powodzi się odczyt z niej.

Jeśli się mylę, niech mnie ktoś poprawi rzecz jasna.

sprawdze jak to bedzie na windowsie dzialac i napisze

Tu jest całkiem dobra stronka opisująca problem: http://users.actcom.co.il/~choo/lupg/tu … emory.html

marcinkk ,

Zapoznaj się z tematem i popraw tytuł tematu na konkretny, mówiący o problemie. W celu dokonania zaleconej korekty proszę użyć przycisku Edytuj przy poście otwierającym ten temat.

Zignorowanie zalecenia będzie skutkowało usunięciem tematu do Kosza.