是否可以同时返回和释放动态分配的数组?
int *mycopy(int *from, int len)
{
int i;
int *to;
to = malloc(len*sizeof(int));
for(i = 0; i < len; ++i) {
to[i] = from[i]
}
return to;
// how do I free the "to" array?
// do i even need to, or does the array only have function scope
// and get deleted when the function exits?
}
或者是
void mycopy(int *from, int *to, int len);
我唯一的选择?
mycopy函数只是一个简单的例子,但在实际代码中,我想嵌套它们,比如像一样调用它
a = mycopy(mycopy(b, 5), 5)
在每次调用函数时不分配更多内存的情况下,如何做到这一点?谢谢
如果返回数组,调用代码必须负责释放它(函数必须而不是释放它)。如果不返回数组,函数必须释放它,但无论如何,该函数都毫无意义。因此,函数不会释放数组。
如果您使用:
void mycopy(int *from, int *to, int len);
调用代码必须进行内存分配。如果您使用:
void mycopy(int *from, int **to, int len);
该函数可以进行分配,但它仍然不能释放它。
但最初的函数更好:它写得很好。你可以这样称呼它:
int b[] = { 1, 2, 3, 9, 2 };
int *a = mycopy(b, sizeof(b)/sizeof(b[0]));
...use a...
free(a);
顺便说一句,您不能嵌套对复制功能的调用—或者,至少,你用不起这个:
a = mycopy(mycopy(b, 5), 5);
它会严重泄露内存。如果你必须进行嵌套调用(为什么?),那么你需要:
int *c;
int *a = mycopy((c = mycopy(b, 5)), 5);
但写起来会更干净、更整洁:
int *a = mycopy(b, 5);
int *c = mycopy(b, 5);
这不太容易出错,更容易理解,并且启动时使用的字符也稍微少一些!
如果您试图在同一个函数中返回AND释放动态分配的数组,那就是自相矛盾。堆(动态)分配的目的是创建一个在函数返回后仍然存在的对象。一旦不再需要,接收者有义务将其释放。
现在,在您的嵌套示例中,内部mycopy(b, 5)
引用已泄漏;你没有把它保存在一个持久变量中。我不知道为什么筑巢这么重要。但讨论起来很有趣,所以假设你坚持嵌套:为了避免内存泄漏,让数组的原始副本是复制完成后的free()
d副本,这样只有副本存活下来。享乐但现在,代码除了浪费时间之外,什么都没做。这让我们回到:也许这是占位符代码。你可能试图做一些有用的事情,但这里没有足够的信息来采取适当的更高层次的观点并重新制定整个策略。
注意,毕竟
a = mycopy(mycopy(b, 5), 5);
没有意义,因为丢失的副本,即你永远无法访问free()
的副本,不仅丢失了,而且是b
指向的原始数据的无用副本,所以这可能适用于另一种没有指针的语言,但在c中,这没有意义。
此外,由于您可以有一个数据副本和多个指向它的指针,除了修改数据副本外,通常不需要复制数据,但制作只读副本是不必要的,您只需要使用指针即可,如果您不想保留原始数据的副本,您也可以通过指针修改它,而不是创建它的副本。
为了正确地调用free,在返回数组的调用方函数中,当您确信不再需要访问数组时,请调用free(array)
,例如
int *x = mycopy(b, 5);
if (x == NULL)
pleaseDoSomething_DoNot_Dereference_x();
int *a = mycopy(x, 5);
if (a == NULL)
pleaseDoSomething_DoNot_Dereference_a();
free(x);
/* Do wahtever you want with a */
free(a);
随心所欲,如
a = mycopy(mycopy(b, 5), 5);
是可能的,但不正确,因为你会导致内存泄漏,而且没有办法这样做,从长远来看,你会学到一件好事,你不能这样做是一个好处,因为这种语法a = mycopy(mycopy(b, 5), 5);
非常误导人。
注意:您不需要编写一个循环来复制内容,只需使用string.h
标准标头中的memcpy()
,这将是mycopy()
函数的健壮版本
int *mycopy(int *from, size_t length)
{
int *to;
to = malloc(length * sizeof(*to));
if (to == NULL)
return NULL;
memcpy(to, from, length);
return to;
}
上面我说了">robust",因为代码检查malloc()
的返回值,即失败时的NULL
。
有时您需要提供自己的函数来释放分配的内存。。。例如,在Windows上,当您调用DLL中的代码并将分配的内存返回给您时,您必须通过调用同一DLL中的free来释放它,否则会发生内存泄漏(最好的情况是堆损坏,最坏的情况是)。。。这是因为MS窗口中的DLL彼此之间以及与主调用程序之间都有各自独立的堆。
这并不总是一件坏事,因为最常见的情况是一个已分配的结构中有指向其他已分配对象的指针,所以您可能需要一个例程来正确释放它。
无论如何,要做到这一点,您应该以这种方式对myfree()
例程进行编码(我以与上面的代码相匹配的方式对其进行了编码):
void myfree( int** tofree )
{
if( tofree != NULL ) {
free( *tofree );
*tofree = NULL;
}
}
您可以用以下方式调用您的函数和此函数:
int *x = mycopy(b, 5);
// then do some things with x, and after:
myfree(&x);
// x is freed, and set to =NULL
MSDN相关文章的链接:http://msdn.microsoft.com/en-us/library/ms235460.aspx