Переменная с памятью, выделенной в другой функции - PullRequest
0 голосов
/ 08 февраля 2019

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

Вот пример, вопрос относительно комментариев:

char** fnTest(char* string) {

    char** rArray = malloc( 2 * sizeof(char*));

    // Same example here. string was technically already malloc'd from main. Is the string here also malloc'd as well?
    rArray[0] = string;

    return rArray;

}

int main() {

    char* inputString = malloc(5);
    strcpy(inputString, "test");

    // Question is in regards to pArray. Will this variable get malloc'd correctly?
    char** pArray;
    pArray = fnTest(inputString);



    // Everythign will be free'd from another function, but to keep it simple I'm not including it here.

    return 0;

}

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

В fnTest указатель string копируется в rArray[0], а указатель rArray возвращается в main(), где он копируется в pArray.

В итоге у вас есть:

                -------
inputString -> |t|e|s|t|
pArray[0]   ->  -------

pArray[1] -> undefined

, где inputString и pArray[0] указывают на одно и то же место.

Если бы вы освободили inputString,pArray[0] больше не будет безопасным для использования, в то время как если вы освободите pArray, входная строка останется действительной.Точно так же вы можете освободить pArray[0] и inputString, так как оба действия освободят один и тот же блок, содержащий "test".Освобождение обоих также будет недействительным.

0 голосов
/ 08 февраля 2019

Если вы хотите выделить внутри функции без назначения возврата выделения обратно в вызывающей функции, то вы не можете просто передать указатель на функцию для выделения.Зачем?C является передачей по значению, и когда переменная передается в качестве параметра, функция получает копию переменной со своим собственным адресом, который сильно отличается от исходного значения в вызывающей программе.Любые изменения, внесенные в переменную в функции, никогда не будут видны обратно в вызывающей стороне.

Чтобы обработать этот сценарий, вы можете передать адрес переменной (например, указатель) и обновить значение по исходному адресу.в памяти.Когда вы говорите о переменной, которая уже является указателем, применяется то же самое, вы должны передать адрес указателя в качестве параметра, чтобы функция получила указатель, содержащий исходный адрес указателя.Затем вы можете выделить / перераспределить, используя исходный адрес указателя и сделать изменения видимыми обратно в вызывающей стороне.Краткий пример может помочь:

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

#define NCHAR 64

void fntest (char **s)
{
    void *tmp = realloc (*s, NCHAR);   /* allocate - using realloc */

    if (!tmp)                          /* validate every allocation */
        perror ("realloc-*s");

    *s = tmp;   /* assign new block of memory (or NULL) to original address */
}

int main (void) {

    char *string = NULL;    /* must be initialized NULL */

    fntest (&string);       /* call fntest to allocate string */

    if (string) {           /* validate allocation succeeded */
        strcpy (string, "some stuff");      /* copy some stuff */
        printf ("string: %s\n", string);    /* output it */
        free (string);      /* don't forget to free what you allocate */
    }
}

Пример использования / вывода

$ ./bin/allocinfn
string: some stuff

Использование памяти / проверка ошибок

$ valgrind ./bin/allocinfn
==7962== Memcheck, a memory error detector
==7962== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==7962== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==7962== Command: ./bin/allocinfn2
==7962==
string: some stuff
==7962==
==7962== HEAP SUMMARY:
==7962==     in use at exit: 0 bytes in 0 blocks
==7962==   total heap usage: 1 allocs, 1 frees, 64 bytes allocated
==7962==
==7962== All heap blocks were freed -- no leaks are possible
==7962==
==7962== For counts of detected and suppressed errors, rerun with: -v
==7962== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Предпочтительная альтернатива - используйте функцию Return

Хотя нет ничего плохого в передаче адреса указателя (и фактически в распределении списков и т. Д. Это требуется)) при простом размещении в отдельной функции вы можете объявить переменную внутри функции, выделить необходимое пространство, проверить выделение выполнено успешно, а затем вернуть указатель на новый блок памяти и назначить его обратно.в main().Это немного упрощает вещи.Например:

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

#define NCHAR 64

char *fntest (size_t size)
{
    void *memptr = malloc (size);     /* simply allocate size bytes */

    if (!memptr)                      /* validate! */
        perror ("malloc-memptr");

    return memptr;                    /* return pointer to new block (or NULL) */
}

int main (void) {

    char *string = fntest (NCHAR);

    if (string) {           /* validate allocation succeeded */
        strcpy (string, "some stuff");      /* copy some stuff */
        printf ("string: %s\n", string);    /* output it */
        free (string);      /* don't forget to free what you allocate */
    }
}

(вывод и проверка памяти одинаковы)

Просмотрите оба и дайте мне знать, если у вас все еще есть вопросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...