关于为变量分配内存,如果我创建一个变量并将其发送到另一个函数,该函数在该函数内分配了内存并将结果返回给我创建的变量,则原始变量是否具有正确的分配内存? / 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;
}
答案 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
inputString
和pArray[0]
指向同一位置。
如果您要释放inputString
,则pArray[0]
将不再安全使用,而如果您释放了pArray
,则输入字符串将保持有效。同样,您可以释放pArray[0]
和inputString
是无效的,因为这两个操作都将释放包含“ test”的同一块。释放两者也将无效。