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.

  1. 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 в другие строки кода. Хорошие уроки от всех участников. Большое спасибо.