Przekazywanie tablicy dwuwymiarowej do funkcji, alokacja i ponowne przekazanie do maina

0

Witam

mam do napisania program, w którym muszę między innymi wykorzystać tablicę dwuwymiarową 4xileśtam, dynamicznie zaalokowaną (alokacja umieszczona w funkcji). Próbowałem dokonać tego przy pomocy funkcji zwracającej za pomocą return wskaźnik do tej tablicy (double **funkcja), niestety mój prowadzący nie zgodził się na takie rozwiązanie (ze względu na brak możliwości wyczyszczenia tablicy z tej funkcji), nalegając, by była to funkcja void, która to będzie pracowała na tablicy bez jej zwracania.

Spróbowałem tego dokonać, skończyło się na takim kodzie

void buduj_tab(double **tab, double ilosc, double okres, double rozdzielczosc)	
{
	int i;
	tab = (double**)malloc(4 * sizeof(double*));
	for (i = 0; i < 4; i++)
	{
		tab[i] = (double*)malloc((int)(floor(ilosc * okres / rozdzielczosc) + 1) * sizeof(double));
	}
}

int main()
{
	double **tab = NULL;
	buduj_tab(tab, ilosc, okres, rozdzielczosc);
	free(tab);
} 

Niestety, do maina nie trafia tablica, w debugowaniu widać, że dalej wynosi ona NULL.
Co jest nie tak? Proszę o pomoc.

3

Przekazywanie parametru przez wartość i referencję

W skrócie: funkcja operuje na kopii wskaźnika, więc po wyjściu z funkcji wskaźnik nadal ma starą wartość (NULL). Argumentem tej funkcji musi być

void buduj_tab(double*** tab, double ilosc, double okres, double rozdzielczosc)
0

Czyli rozumiem, że kod powinien wyglądać tak:

void buduj_tab(double ***tab, double ilosc, double okres, double rozdzielczosc)    
{
    int i;
    *tab = (double**)malloc(4 * sizeof(double*));
    for (i = 0; i < 4; i++)
    {
        *(tab[i]) = (double*)malloc((int)(floor(ilosc * okres / rozdzielczosc) + 1) * sizeof(double));
    }
}
 
int main()
{
    double **tab = NULL;
    buduj_tab(&tab, ilosc, okres, rozdzielczosc);
    free(tab);
}  

Tylko w takim przypadku alokuje się tablica o jednej kolumnie - przy próbie alokacji kolejnych program krzyczy, że zapisuje w niepoprawnej lokalizacji. Czy popełniam jeszcze jakiś błąd?

2
(*tab)[i]

bo nawiasy kwadratowe mają wyższy priorytet niż gwiazdka, ale poza tym tak.

0

Dzięki! Temat do zamknięcia :D

0
zielonek430 napisał(a):

Próbowałem dokonać tego przy pomocy funkcji zwracającej za pomocą return wskaźnik do tej tablicy (double **funkcja), niestety mój prowadzący nie zgodził się na takie rozwiązanie (ze względu na brak możliwości wyczyszczenia tablicy z tej funkcji),

Nie rozumiem. Nie można zwolnić takiej tablicy? Jeśli zna się jej pierwszy wymiar, to można: http://ideone.com/57d9K7 Valgrind nie wykazuje problemów.

zielonek430 napisał(a):

nalegając, by była to funkcja void, która to będzie pracowała na tablicy bez jej zwracania.

No i? Przecież tu jest ten sam problem, nie można tej tablicy zwolnić od tak sobie.

zielonek430 napisał(a):

Czyli rozumiem, że kod powinien wyglądać tak:

#include <stdlib.h>
#include <math.h>

void buduj_tab(double ***tab, double ilosc, double okres, double rozdzielczosc)    
{
    int i;
    *tab = (double**)malloc(4 * sizeof(double*));
    for (i = 0; i < 4; i++)
    {
        (*tab)[i] = (double*)malloc((int)(floor(ilosc * okres / rozdzielczosc) + 1) * sizeof(double));
    }
}
 
int main()
{
    double **tab = NULL;
    buduj_tab(&tab, 5.0, 8.6, 2.4);
    free(tab);
}  

Przecież tu jest wyciek pamięci! Nie rozumiem, co przekazywanie tablicy jako argument funkcji ma naprawić?

==3695== Memcheck, a memory error detector
==3695== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3695== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==3695== Command: ./wtf
==3695== 
==3695== 
==3695== HEAP SUMMARY:
==3695==     in use at exit: 576 bytes in 4 blocks
==3695==   total heap usage: 5 allocs, 1 frees, 608 bytes allocated
==3695== 
==3695== LEAK SUMMARY:
==3695==    definitely lost: 576 bytes in 4 blocks
==3695==    indirectly lost: 0 bytes in 0 blocks
==3695==      possibly lost: 0 bytes in 0 blocks
==3695==    still reachable: 0 bytes in 0 blocks
==3695==         suppressed: 0 bytes in 0 blocks
==3695== Rerun with --leak-check=full to see details of leaked memory
==3695== 
==3695== For counts of detected and suppressed errors, rerun with: -v
==3695== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Nie jestem żadnym ekspertem od C, więc moje pytania nie były (tylko) retoryczne.

Poważnie, mógłby ktoś wytłumaczyć, jaki takie podejście ma sens i cel?

1

Jest wyciek, bo najpierw powinien zwolnic pamięć (tab)[i] elementów, a następnie tab....

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