funkcja do zwalniania dynamicznie przydzielonej pamięci

0

witam forumowiczów serdecznie, mam następujący problem: napisałem funkcje do generowania macierzy z dynamicznie alokowaną pamięcią. następnie napisałem funkcję która pozwoli mi zwolnić przydzieloną wcześniej pamięć. program po uruchomieniu powoduje że komputer wydaje dźwięk błędu i program się zawiesza. jeśli to problem trywialny to wybaczcie.

#include "stdafx.h"

#include "stdio.h"

#include "malloc.h"

#include "time.h"

#include "stdlib.h"

int** generowanie(int m, int n)

{

	srand(time(0));

	int **wsk = (int**)malloc(sizeof(wsk)*m);

	for (int i = 0; i <= m; i++)

	{

		wsk[i] = (int*)malloc(sizeof(wsk)*n);

	}

	for (int i = 0; i <= m-1; i++)

	{

		for (int j = 0; j <= n-1; j++)

		{

			wsk[i][j] = rand()%100;

		}

	}

    return wsk;

}

void zwalnianiePamieci(int **wsk, int n)

{

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

	{

		free(wsk[i]);

	}

	free(wsk);

}

int main()

{

	int m = 3;

	int n = 3;


	int **w = generowanie(m, n);

	zwalnianiePamieci(w, n);


	return 0;
}

 
4
    int **wsk = (int**)malloc(sizeof(wsk)*m);
 
    for (int i = 0; i <= m; i++)
 

Wychodzisz poza zakres, poza tym sizeof na złej zmiennej użyłeś (wsk zamiast *wsk, chociaż w tym przypadku to nie boli).

Używaj < jak człowiek.

1
    for (int i = 0; i <= m-1; i++)
for (int i = 0; i < m; i++)
0

można również krócej i prościej tą alokację:

 

// UWAGA!!!!! Ten przyklad ma na celu pokazanie, ze chodzi mi o alokacje jednego, ciaglego bloku pamieci, zamiast miliona
// podalokacji. Ten przyklad nie dziala i nie ma prawa dzialac - wymaga dopracowania, ktore znajduje sie w dalszej czesci watku. 
// Wszystkich "pseudo-znawcow" jezyka C zachecam do zaparzenia sobie melisy i zastanowienia sie jak doprowadzic to do dzialania
// zamiast wszechobecnych madrosci. Rozumiem, ze sie cieszycie, ze widzicie blad, ale to nie powod zeby wyciagac pochopne wnioski
// na temat mojej znajomosci jezyka C. 
int **wsk = malloc(sizeof(wsk)*m*n);

for(int i = 0 ; i < m ; i++)
    for(int j = 0; j < n ; j++)
        wsk[i][j] = rand()%100;

free(wsk); 
2

Tak, ale zakładaliśmy, że on też chce poprawnie. Twój kod to jedno wielkie UB.

0

kq - mógłbyś uzasadnić swoją wypowiedź? Dlaczego uważasz alokowanie 10 tablic osobno zamiast jednego dużego bloku pamięci za lepsze?

1

Nic takiego nie napisałem. Napisałem tylko, że Twój kod jest pełen UB.

0

Dobrze, ale ciągle proszę o uzasadnienie :)

2

Czy "na wszystkich popularnych architekturach i kompilatorach powoduje crash z powodu naruszenia ochrony pamięci" jest dla Ciebie uzasadnieniem, czy takimi pierdołami się nie przejmujesz?

http://melpon.org/wandbox/permlink/8lwBGe98u2u8F98Z

1

Dobrze, ale ciągle proszę o uzasadnienie

Uwaga, uzasadnienie: to nie działa.

To nawet nie ma prawa działać.
Tablica dwuwymiarowa to nie to samo co tablica wskaźników.

Najpierw alokujesz tablicę rozmiaru m*n wskaźników na wskaźnik na int.
Nie dość, że intencją było zaalokowanie tablicy której elementami są int a nie int* ani int**, więc zakładasz że rozmiar inta jest równy rozmiarowi wskaźnika, co jest prawdą tylko na niektórych platformach, to jeszcze wynik przypisujesz do int** zamiast int***, więc kod jest zły nawet jeśli chodziłoby o tablicę wskaźników na wskaźnik.

Potem odwołujesz się do elementu wsk[i], który ma typ int*, którego w żaden sposób nie inicjujesz a indeksujesz znowu przez [j]. UB.

0

Ech... Skąd ta agresja wśród Was ludzie, to ja nie wiem :) Zaszałałem, z tymi podwójnymi wskaźnikami, bo faktycnzie, jeszcze je trzeba uzupełnić, jednakże kiedy tworzycie dwuwymiarową tablicę na stosie, to jest ona ciągłym blokiem pamięci i założę, się, że istnieje możliwość, aby i na stercie takową stworzyć. Nie wjeżdżajcie tak na mnie agresywnie, bo to nie na miejscu według mnie - ja nikogo nie atakowałem :P

2

Ech, ludzie małej wiary. Sami jeszcze musicie się sporo nauczyc :)

Proszę, oto działający kod w ANSII C:


int main(void) {
	int row = 10 , col = 20;
	int (*mat)[col];
	mat=(int (*)[col])malloc(sizeof(*mat)*row);
	int i , j;
	
	for(i = 0; i < row ; i++)
	{
		for(j = 0; j < col ; j++)
		{
			mat[i][j] = j * i;
		}
	}
	
	for(i = 0; i < row ; i++)
	{
		for(j = 0; j < col ; j++)
		{
	
			printf("mat[%d][%d] = %d\n" , i , j , mat[i][j]);
		}
	}
	
	// your code goes here
	return 0;
}
0

Ech, ludzie małej wiary. Sami jeszcze musicie się sporo nauczyc :)

Proszę, oto działający kod w ANSII C:

To że coś działa, to nie znaczy, że jest poprawne.

ms:
Error 1 error C2057: expected constant expression
Error 2 error C2466: cannot allocate an array of constant size 0
Error 3 error C2057: expected constant expression
Error 4 error C2466: cannot allocate an array of constant size 0
Warning 5 warning C4013: 'malloc' undefined; assuming extern returning int
Warning 6 warning C4034: sizeof returns 0
Error 7 error C2036: 'int ()[]' : unknown size
Error 8 error C2036: 'int (
)[]' : unknown size
9 IntelliSense: expression must have a constant value
10 IntelliSense: expression must have a constant value

dla gcc:
C:\Users\MMiS\Documents\Code Blocks\main.c|6|warning: implicit declaration of function 'malloc' [-Wimplicit-function-declaration]|
C:\Users\MMiS\Documents\Code Blocks\main.c|6|warning: incompatible implicit declaration of built-in function 'malloc'|
C:\Users\MMiS\Documents\Code Blocks\main.c|6|note: include '<stdlib.h>' or provide a declaration of 'malloc'|

Poprawny kod to taki, który nie wywala błędów ani ostrzeżeń.

0

Serio? Czepiasz sie, ze malloca nie widzi? :) Mysle, ze to nie to bylo objektem tego exampla :)

Zmien standard kompilacji, ii podaj wersje MS, ktora uzywasz.

Poza tym jak chcesz, to uzywaj tablicy wskaznikow zamiast tablicy dwuwymiarowej :) Mnie to rybka :)

0
int **allocIntMatrix(int n, int m)
{
	int **result;
	// wyrównaj do paragrafu
	int rowSize = (m+3) & ~3u; 
	int colSize = (n+3) & ~3u;
	int size = sizeof(*result) * colSize + sizeof(**result) * rowSize * n;

	result = (int **)malloc(size);
	if (result) {
		int i;
		for (i=0; i < n; ++i) {
			result[i] = ((int*)&result[colSize]) + rowSize*i;
		}
	}

	return result;
}

http://ideone.com/4hsGZL

0

Tak, to GCC:

 
#include <stdio.h>
#include <stdlib.h>

#define AllocateArray(r,c,t)	_AllocateArray(r,c,sizeof(t))

void * _AllocateArray( size_t Row , size_t Column , size_t TypeSize )
{
    return malloc(Row*Column*TypeSize);	
}

void FillArray( size_t Row , size_t Column , int (*Array)[Column] )
{
	int r = 0 , c = 0;
	
	for(r = 0 ; r < Row ; r++ )
	{
		for( c = 0 ; c < Column ; c++ )
		{
			Array[r][c] = r * c;
		}
	}
}

void PrintArray( size_t Row , size_t Column , int (*Array)[Column] )
{
	int r = 0 , c = 0;
	
	for(r = 0 ; r < Row ; r++ )
	{
		for( c = 0 ; c < Column ; c++ )
		{
			printf("[%d][%d] = %d\n" , r , c , Array[r][c]);
		}
	}
}

int main(void) {
	void * array = AllocateArray(20,10,int);
	FillArray(20,10,array);
	PrintArray(20,10,array);
	return 0;
}

To zeby odeprzec atak, ze nie da sie tego uzaleznic od danych wejsciowych. Korzystajmy z dobrodziejstw, jakie z ogromnym trudem zapewniaja nam programisci kompilatorow, jesli tylko mozemy. Owszem, nie wszedzie mozna wszytkiego uzywac (sam w pracy jestem bardzo ograniczony ze wzgledu na ciagle wspieranie DOSa przez nasz projekt), ale nie mowmy ludziom, ze nie ma lepszych rozwiazan, bo na systemie windows 3.11 nie bedzie cos dzialac. Piszmy najlepszy kod, jaki jestesmy wstanie zapewnic na danej platformie. Moze wtedy nastepna wersja windowsa nie bedzie potrzebowala 4GB pamieci, zeby uruchomic przegladarke...

3

Dziwi mnie wiele opinii tutaj. Serio według kogoś lepiej mallocować w pętli i jest to bardziej czytelne? A później na koniec w pętli trzeba wszystko zwalniać. Nie, nie jest to bezpieczne ani logiczne. Na szczęście programiści z doświadczeniem tępią takie zachowania - ja też tak czynię :)

Edit:
Wybraźmy sobie sytuację, że chcemy mieć trójwymiarową tablicę. Chciałbym zauważyć alternatywną implementację, która jest "czytelna".

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