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
8 54

8 ответов:

вы должны передать указатель на указатель в качестве параметра функции.

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; 
} 

как я должен передать указатель на функция и размещает память для передается указатель изнутри вызываемого функции?

спросите себя: если вы должны были написать функцию, которая должна была вернуть int, как бы вы это сделали?

вы либо возвращаете его напрямую:

int foo(void)
{
    return 42;
}

или верните его через выходной параметр, добавив уровень абстрагирование (т. е. с помощью 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(...);
}

Если вы хотите, чтобы ваша функция изменила сам указатель, вам нужно будет передать его как указатель на указатель. Вот упрощенный пример:

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);
}

вам нужно передать указатель по ссылке, а не копия параметр в функции 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) и "ошибка: ...- внутри

это не имеет смысла:

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);

в исходном коде, когда вы передавали input_image в функцию alloc_pixels, компилятор создавал его копию (т. е. ptr) и сохранял значение в стеке. Вы назначаете значение, возвращенное malloc ptr. Это значение теряется, как только функция возвращается в main и стек разматывается. Таким образом, память по-прежнему выделяется в куче, но место памяти никогда не сохранялось (или не назначалось )input_image, следовательно, проблема.

Вы можете изменить сигнатуру функции alloc_pixels, которые было бы проще понять, и Вам также не потребуется дополнительная переменная "статус".

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;
}

вы можете вызвать вышеуказанную функцию в 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;

}

назначение параметров будет работать только в том случае, если вы установите значение its адрес.

есть 2 пункта, которые вы должны знать, прежде чем пытаться решить эту проблему:
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's value will be 1

Итак, если вы хотите изменить i в функции, вам нужно знать разницу между вещью и ее копией:

копировать общий элемент стоимостью С вещью, а не адрес.

и это их единственное отличие.

таким образом, единственный способ изменить i в функции-это использовать адрес i.

например, есть новая функция fun_addr:

void fun_addr(int *i) {
    *i = some_value;
}

таким образом, вы можете изменить значение i.

  1. Танос:

ключевым моментом в функции fun_addr является то, что вы передали адрес функции. И вы можете изменить значение, хранящееся по этому адресу.

что будет делать Мэллок?

malloc выделит новое пространство памяти, и верните указатель, указывающий на этот адрес назад.

смотреть на это инструкция:

int *array = (int*) malloc(sizeof(int) * SIZE);

то, что вы делаете, это пусть значение массива равно адресу, возвращенному malloc.

посмотреть? Это тот же самый вопрос, постоянно присваивающий значение параметру, переданному функции. На данный момент, значение address.

теперь назначьте адрес (возвращенный malloc) на адрес(сохраняет старый адрес).

поэтому код должен быть:

void fun_addr_addr(int **p) {
    *p = (int*) malloc(sizeof(int) * SIZE);
}

это будет работать.

единственный способ, которым я мог бы получить указатель на решение указателя для работы с аналогичной проблемой, которую я имел для этой функции

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