Programowanie w C: malloc () wewnątrz innej funkcji
Potrzebuję pomocy przy malloc()
wewnątrz innej funkcji.
Przekazuję wskaźnik i Rozmiar do funkcji z mojego main()
i chciałbym przydzielić pamięć dla tego wskaźnika dynamicznie używając malloc()
z wewnątrz tej wywołanej funkcji, ale widzę to.... pamięć, która jest przydzielana, jest dla wskaźnika zadeklarowanego w mojej wywołanej funkcji, a nie dla wskaźnika, który jest wewnątrz main()
.
Jak przekazać wskaźnik do funkcja i przydzielić pamięć dla przekazanego wskaźnika z wnętrza wywołanej funkcji?
Napisałem następujący kod i otrzymuję wynik, jak pokazano poniżej.
Źródło:
int main()
{
unsigned char *input_image;
unsigned int bmp_image_size = 262144;
if(alloc_pixels(input_image, bmp_image_size)==NULL)
printf("\nPoint2: Memory allocated: %d bytes",_msize(input_image));
else
printf("\nPoint3: Memory not allocated");
return 0;
}
signed char alloc_pixels(unsigned char *ptr, unsigned int size)
{
signed char status = NO_ERROR;
ptr = NULL;
ptr = (unsigned char*)malloc(size);
if(ptr== NULL)
{
status = ERROR;
free(ptr);
printf("\nERROR: Memory allocation did not complete successfully!");
}
printf("\nPoint1: Memory allocated: %d bytes",_msize(ptr));
return status;
}
WYJŚCIE PROGRAMU:
Point1: Memory allocated ptr: 262144 bytes
Point2: Memory allocated input_image: 0 bytes
8 answers
Musisz przekazać wskaźnik do wskaźnika jako parametr do swojej funkcji.
int main()
{
unsigned char *input_image;
unsigned int bmp_image_size = 262144;
if(alloc_pixels(&input_image, bmp_image_size) == NO_ERROR)
printf("\nPoint2: Memory allocated: %d bytes",_msize(input_image));
else
printf("\nPoint3: Memory not allocated");
return 0;
}
signed char alloc_pixels(unsigned char **ptr, unsigned int size)
{
signed char status = NO_ERROR;
*ptr = NULL;
*ptr = (unsigned char*)malloc(size);
if(*ptr== NULL)
{
status = ERROR;
free(*ptr); /* this line is completely redundant */
printf("\nERROR: Memory allocation did not complete successfully!");
}
printf("\nPoint1: Memory allocated: %d bytes",_msize(*ptr));
return status;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-31 18:18:00
Jak przekazać wskaźnik do funkcja i przydzielanie pamięci dla przekazywany wskaźnik od wewnątrz wywołanego funkcja?
Zadaj sobie pytanie: gdybyś musiał napisać funkcję, która musiałaby zwrócić int
, Jak byś to zrobił?
Zwróciłbyś go bezpośrednio:
int foo(void)
{
return 42;
}
Lub zwróć go poprzez parametr wyjściowy, dodając poziom indrection (tj. używając int*
zamiast int
):
void foo(int* out)
{
assert(out != NULL);
*out = 42;
}
Więc kiedy zwracasz typ wskaźnika (T*
), to to samo: albo zwracasz typ wskaźnika bezpośrednio:
T* foo(void)
{
T* p = malloc(...);
return p;
}
Lub dodajesz jeden poziom indrection:
void foo(T** out)
{
assert(out != NULL);
*out = malloc(...);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-25 20:12:13
Jeśli chcesz, aby Twoja funkcja zmodyfikowała sam wskaźnik, musisz przekazać go jako wskaźnik do wskaźnika. Oto uproszczony przykład:
void allocate_memory(char **ptr, size_t size) {
void *memory = malloc(size);
if (memory == NULL) {
// ...error handling (btw, there's no need to call free() on a null pointer. It doesn't do anything.)
}
*ptr = (char *)memory;
}
int main() {
char *data;
allocate_memory(&data, 16);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-14 22:49:21
Musisz przekazać wskaźnik przez referencję, a nie przez kopię, parametr w funkcji alloc_pixels
wymaga ampersand&, aby przekazać z powrotem adres wskaźnika - to jest wywołanie przez referencję w języku C speak.
main() { unsigned char *input_image; unsigned int bmp_image_size = 262144; if(alloc_pixels(&input_image, bmp_image_size)==NULL) printf("\nPoint2: Memory allocated: %d bytes",_msize(input_image)); else printf("\nPoint3: Memory not allocated"); } signed char alloc_pixels(unsigned char **ptr, unsigned int size) { signed char status = NO_ERROR; *ptr = NULL; *ptr = (unsigned char*)malloc(size); if((*ptr) == NULL) { status = ERROR; /* free(ptr); printf("\nERROR: Memory allocation did not complete successfully!"); */ } printf("\nPoint1: Memory allocated: %d bytes",_msize(*ptr)); return status; }
Skomentowałem dwie linijki free(ptr)
i " błąd: ..."wewnątrz alloc_pixels
funkcji, ponieważ jest to mylące. Nie trzeba free
Wskaźnik, jeśli alokacja pamięci nie powiodła się.
Edit: po obejrzeniu msdn link dostarczony przez OP, sugestia, próbka kodu jest taka sama jak wcześniej w mojej odpowiedzi.... ale...Zmień specyfikator formatu na %u
dla typu size_t
, w wywołaniu printf(...)
w wywołaniu main()
.
main() { unsigned char *input_image; unsigned int bmp_image_size = 262144; if(alloc_pixels(&input_image, bmp_image_size)==NULL) printf("\nPoint2: Memory allocated: %u bytes",_msize(input_image)); else printf("\nPoint3: Memory not allocated"); }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-15 10:59:33
To nie ma sensu:
if(alloc_pixels(input_image, bmp_image_size)==NULL)
alloc_pixels
zwraca a signed char
(ERROR
or NO_ERROR
) i porównujesz go z NULL
(który ma być używany do wskaźników).
Jeśli chcesz, aby input_image
została zmieniona, musisz przekazać do niej wskaźnik do alloc_pixels
.
alloc_pixels
podpis będzie następujący:
signed char alloc_pixels(unsigned char **ptr, unsigned int size)
Nazwałbyś to tak:
alloc_pixels(&input_image, bmp_image_size);
I alokacja pamięci
*ptr = malloc(size);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-14 22:50:27
W Twoim kodzie początkowym , kiedy przekazywałeś input_image do funkcji alloc_pixels, kompilator tworzył jej kopię (tj. ptr) i przechowywał wartość na stosie. Przypisujesz wartość zwróconą przez malloc do PST. Wartość ta jest tracona, gdy funkcja powróci do main i stos się odwija. Tak więc pamięć jest nadal przydzielana na stercie, ale lokalizacja pamięci nigdy nie została zapisana (lub przypisana do )input_image, stąd problem.
Możesz zmienić podpis funkcji alloc_pixels, co byłoby prostsze do zrozumienia i nie będzie wymagało dodatkowej zmiennej "status".
unsigned char *alloc_pixels(unsigned int size)
{
unsigned char *ptr = NULL;
ptr = (unsigned char *)malloc(size);
if (ptr != NULL)
printf("\nPoint1: Memory allocated: %d bytes",_msize(ptr));
return ptr;
}
Możesz wywołać powyższą funkcję w main:
int main()
{
unsigned char *input_image;
unsigned int bmp_image_size = 262144;
if((input_image = alloc_pixels(bmp_image_size))==NULL)
printf("\nPoint3: Memory not allocated");
else
printf("\nPoint2: Memory allocated: %d bytes",_msize(input_image));
return 0;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-15 06:42:42
Przypisanie parametrów będzie działać tylko wtedy, gdy ustawisz wartość na jej adres .
Są 2 punkty, które powinieneś wiedzieć, zanim spróbujesz rozwiązać ten problem:
1. C Funkcja: wszystkie parametry przekazane do funkcji będą kopiowane w funkcji.
Oznacza to, że każde przypisanie dokonane w funkcji nie będzie miało wpływu na zmienne spoza funkcji, pracujesz nad kopią właściwie:
int i = 1;
fun(i);
printf("%d\n", i);
//no matter what kind of changes you've made to i in fun, i's value will be 1
Więc, jeśli chcesz zmienić i w funkcji, musisz znać różnicę między rzeczą a jej kopią:
I to ich jedyna różnica.Kopia dzieliła wartość z rzeczą, ale nie adres .
Więc jedynym sposobem na zmianę i w funkcji jest użycie adresu i.
Na przykład, istnieje nowa funkcja fun_addr:
void fun_addr(int *i) {
*i = some_value;
}
W ten sposób, można zmienić i ' S wartość.
- malloc :
Kluczowym punktem funkcji fun_addr jest przekazanie adresu do funkcji. I możesz zmienić wartość przechowywaną w tym adresie.
Co zrobi malloc?Malloc przydzieli nową przestrzeń pamięci i zwróci wskaźnik wskazujący na ten adres z powrotem .
Spójrz na tę instrukcję:
int *array = (int*) malloc(sizeof(int) * SIZE);
To co robisz to niech wartość array jest równa adresowi zwracanemu przez malloc.
Widzisz? Jest to to samo pytanie, trwale przypisując wartość parametrowi przekazywanemu funkcji. W tym momencie wartością jestaddress
.
Teraz Przypisz adres (zwrócony przez malloc) do adresu (przechowuje stary adres).
Więc kod powinien być:
void fun_addr_addr(int **p) {
*p = (int*) malloc(sizeof(int) * SIZE);
}
To zadziała.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-21 11:10:34
Jedyny sposób, w jaki mogłem uzyskać wskaźnik do rozwiązania wskaźnika, aby działał na podobny problem, który miałem dla tej funkcji
BOOL OpenBitmap2 ( LPCTSTR pszFileName, char** pszBMPFile)
Było poprzez przypisanie tymczasowego wskaźnika do przechowywania adresu
char* BMPFile;
{ BMPFile = (char*)GlobalAlloc(GPTR, dwFileSize + 1); // allocate storage using GlobalAlloc + 1 for null term string
Następnie przypisanie go
{* pszBMPFile = BMPFile; return (0);} // Error = False
Każdy komentarz, dlaczego używanie "* pszBMPFile" bezpośrednio z GlobalAlloc nie działa, będzie mile widziany. Odpowiedziałem na własne pytanie. Zapomniałem przenieść " * " z pszBMPFile w innych linijkach kodu. Dobre lekcje z wszystkich współpracownicy. Wielkie dzięki.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-25 23:18:28