在另一个函数中分配内存的变量

时间:2019-02-08 20:11:52

标签: c string pointers memory malloc

关于为变量分配内存,如果我创建一个变量并将其发送到另一个函数,该函数在该函数内分配了内存并将结果返回给我创建的变量,则原始变量是否具有正确的分配内存? / p>

这是一个例子,关于评论的问题:

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 :(得分:1)

如果要在函数内分配而不在调用函数中分配分配的返回值,则不能简单地将指针传递给要分配的函数。为什么? 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)

首选方案-利用函数返回

尽管传递指针的地址没有错(实际上是在列表分配等中。这是必需的),但只要在单独的函数中进行分配,则可以在函数内声明变量,然后分配所需空间,验证分配成功,然后返回指向新内存块的指针,并将其分配回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 */
    }
}

(输出和内存检查相同)

仔细研究一下,让我知道您是否还有疑问。

答案 1 :(得分:1)

fnTest中,将指针string复制到rArray[0],然后将指针rArray返回到main(),并在其中复制 pArray

最后,您有:

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

pArray[1] -> undefined

inputStringpArray[0]指向同一位置。

如果您要释放inputString,则pArray[0]将不再安全使用,而如果您释放了pArray,则输入字符串将保持有效。同样,您可以释放pArray[0]inputString是无效的,因为这两个操作都将释放包含“ test”的同一块。释放两者也将无效。