Zadziwiającym jest to, że taka alokacja jest możliwa:
#include<stdlib.h>
#define N 5
struct Pole
{
int wartosc;
int cena;
} tab[5][5];
int main()
{
int i;
struct Pole **tab = (struct Pole**)malloc(N*sizeof(struct Pole*));
for(i=0;i<N;i++)
{
tab[i]=(struct Pole*)malloc(N*sizeof(struct Pole));
}
for(i=0; i<N; i++)
free(tab[i]);
free(tab);
return 0;
}
Valgrind nie wyrzuca żadnych błędów:
==8415== Memcheck, a memory error detector
==8415== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8415== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8415== Command: ./c_programming
==8415==
==8415==
==8415== HEAP SUMMARY:
==8415== in use at exit: 0 bytes in 0 blocks
==8415== total heap usage: 6 allocs, 6 frees, 220 bytes allocated
==8415==
==8415== All heap blocks were freed -- no leaks are possible
==8415==
==8415== For counts of detected and suppressed errors, rerun with: -v
==8415== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Naturalnie posiadając tak zdefiniowaną strukturę mamy już przydzieloną pamięć i nie trzeba jej dynamicznie alokować. Pisząc w kodzie programu:
#include<stdlib.h>
#define N 5
struct Pole
{
int wartosc;
int cena;
} tab[5][5];
int main()
{
tab[0][0].wartosc = 2;
tab[0][0].cena = 1;
tab[4][4].wartosc = 3;
tab[4][4].cena = 6;
return 0;
}
...korzystamy z już zaalokowanej pamięci. Oczywiście również o żadnym wycieku pamięci nie może być mowy:
==8451== Memcheck, a memory error detector
==8451== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8451== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8451== Command: ./c_programming
==8451==
==8451==
==8451== HEAP SUMMARY:
==8451== in use at exit: 0 bytes in 0 blocks
==8451== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==8451==
==8451== All heap blocks were freed -- no leaks are possible
==8451==
==8451== For counts of detected and suppressed errors, rerun with: -v
==8451== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Moim zdaniem takie alokowanie pamięci to UB i po takim procederze tab
wskazuje na stertę "przesłaniając" wcześniej zaalokowaną statycznie pamięć.. Masz już tablicę 5 x 5 gotową do użytku więc po co chcesz alokować dynamicznie pamięć? Bez sensu.
EDIT: rzecz jasna zmienna lokalna przesłania globalną i nie ma tutaj żadnego UB, co nie zmienia faktu, że to bez sensu :)