C Программирование: malloc() внутри другой функции
Мне нужна помощь с malloc()
внутри другой функции.
Я передаю указатель и размер в функцию из моего main()
, и я хотел бы динамически выделять память для этого указателя, используя malloc()
изнутри которая называется функцией, но я вижу, что.... память, которая получает выделенную, предназначена для указателя, объявленного в моей вызываемой функции, а не для указателя, который находится внутри main()
.
Как передать указатель на функцию и выделить память для переданного указателя внутри вызываемой функции?
Я написал следующий код, и я получаю вывод, как показано ниже.
Источник:
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;
}
ПРОГРАММНЫЙ ВЫХОД:
Point1: Memory allocated ptr: 262144 bytes
Point2: Memory allocated input_image: 0 bytes
Ответы
Ответ 1
Вам нужно передать указатель на указатель в качестве параметра вашей функции.
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;
}
Ответ 2
Как передать указатель на функции и выделить память для пройденный указатель изнутри вызываемого функция?
Спросите себя: если вам нужно написать функцию, которая должна была вернуть int
, как вы это сделаете?
Вы либо вернете его напрямую:
int foo(void)
{
return 42;
}
или вернуть его через выходной параметр, добавив уровень indirection (т.е. используя int*
вместо int
):
void foo(int* out)
{
assert(out != NULL);
*out = 42;
}
Итак, когда вы возвращаете тип указателя (T*
), это то же самое: вы либо возвращаете тип указателя напрямую:
T* foo(void)
{
T* p = malloc(...);
return p;
}
или вы добавите один уровень косвенности:
void foo(T** out)
{
assert(out != NULL);
*out = malloc(...);
}
Ответ 3
Если вы хотите, чтобы ваша функция изменяла сам указатель, вам нужно передать его как указатель на указатель. Здесь упрощенный пример:
void allocate_memory(char **ptr, size_t size) {
void *memory = malloc(size);
if (memory == NULL) {
// ...error handling (btw, there 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);
}
Ответ 4
Вам нужно передать указатель по ссылке, а не путем копирования, параметр в функции alloc_pixels
требует амперсанда и передать обратно адрес указателя - вызов по ссылке в C говорят.
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;
}
Я прокомментировал две строки free(ptr)
и "ERROR:..." в функции alloc_pixels
, поскольку это путает. Вам не нужно указывать free
указатель, если сбой памяти не удался.
Изменить:. Посмотрев ссылку msdn, предоставленную OP, предложение, образец кода аналогичен предыдущему в моем ответе.... но... измените спецификатор формата на %u
для типа size_t
в вызове printf(...)
в 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");
}
Ответ 5
Это не имеет смысла:
if(alloc_pixels(input_image, bmp_image_size)==NULL)
alloc_pixels
возвращает a signed char
(ERROR
или NO_ERROR
), и вы сравниваете его с NULL
(который предполагается использовать для указателей).
Если вы хотите изменить input_image
, вам нужно передать указатель на него alloc_pixels
.
Подпись alloc_pixels
будет следующей:
signed char alloc_pixels(unsigned char **ptr, unsigned int size)
Вы бы назвали это следующим образом:
alloc_pixels(&input_image, bmp_image_size);
И выделение памяти
*ptr = malloc(size);
Ответ 6
В исходном коде, когда вы передавали input_image функции alloc_pixels, компилятор создавал его копию (т.е. ptr) и сохранял значение в стеке. Вы присваиваете значение, возвращаемое malloc, на ptr. Это значение теряется, как только функция возвращается к основному, и пакет распадается. Таким образом, память по-прежнему выделяется в куче, но память не была сохранена в (или назначена) в input_image, поэтому проблема.
Вы можете изменить подпись функции alloc_pixels, которую было бы проще понять, и вам не потребуется дополнительная переменная '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;
}
Вы можете вызвать указанную выше функцию в главном меню:
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;
}
Ответ 7
Назначение параметров будет работать, только если вы установите его значение .
Есть два момента, которые вы должны знать, прежде чем пытаться решить эту проблему:
1. Функция C: все параметры, которые вы передали функции, будут копией в функции.
Это означает, что каждое присваивание, которое вы сделали в этой функции, не повлияет на переменные вне функции, вы действительно работаете над копией:
int i = 1;
fun(i);
printf("%d\n", i);
//no matter what kind of changes you've made to i in fun, i value will be 1
Итак, если вы хотите изменить я в функции, вам нужно знать разницу между вещью и ее копией:
Копия разделила значение на предмет, но не адрес.
И это их единственное различие.
Таким образом, единственный способ изменить я в функции - использовать адрес i.
Например, есть новая функция fun_addr:
void fun_addr(int *i) {
*i = some_value;
}
Таким образом, вы можете изменить значение i.
- malloc:
Ключевым моментом функции fun_addr является то, что вы передали адрес функции. И вы можете изменить значение, сохраненное в этом адресе.
Что будет делать malloc?
malloc будет выделять новое пространство памяти, а вернуть указатель, указанный на этот адрес.
Посмотрите на эту инструкцию:
int *array = (int*) malloc(sizeof(int) * SIZE);
То, что вы делаете, означает, что значение массива равно адресу, возвращаемому malloc.
См? Это тот же вопрос, который постоянно присваивает значение параметру, переданному функции. В этот момент значение address
.
Теперь назначьте адрес (возвращаемый malloc) на адрес (сохраняет старый адрес).
Таким образом, код должен быть:
void fun_addr_addr(int **p) {
*p = (int*) malloc(sizeof(int) * SIZE);
}
Этот будет работать.
Ответ 8
Единственный способ получить указатель на решение указателя для работы с аналогичной проблемой, которую я имел для этой функции
BOOL OpenBitmap2 ( LPCTSTR pszFileName, char** pszBMPFile)
Был ли задан временный указатель для хранения адреса
char* BMPFile;
{ BMPFile = (char*)GlobalAlloc(GPTR, dwFileSize + 1); // allocate storage using GlobalAlloc + 1 for null term string
затем переназначив его
{* pszBMPFile = BMPFile; return (0);} // Error = False
Любые комментарии о том, почему использование "* pszBMPFile" непосредственно с GlobalAlloc не работали, будут оценены.
Я ответил на свой вопрос. Я забыл переносить "*" через pszBMPFile в другие строки кода. Хорошие уроки от всех участников. Большое спасибо.