这里非常基本的问题,我对C中记忆的传递有点不确定。
如果我有以下
CGPoint* tileForCoordinates (CGPoint position, short width, short height)
{
CGPoint *tileCoordinate = (CGPoint*)malloc(sizeof(CGPoint));
tileCoordinate->xTile = (position.xPosition / width);
tileCoordinate->yTile = (position.yPosition / height);
return tileCoordinate;
}
我想在另一个源文件中调用它或者其他什么,我会在上面声明一个指针并返回它吗?如果是这样,当我打电话来自其他类别时,例如
CGPoint *currentTilePosition = tileForCoordinates(curPosition, 50, 50);
malloc返回的指针会发生什么?它应该被释放还是故事? :)
答案 0 :(得分:4)
你可以将tileCoordinate作为参数传递给函数调用吗?这样,调用者就会发现更容易记住malloc / calloc和free。
答案 1 :(得分:4)
malloc()
声明的指针将是当前正在执行的函数的堆栈帧中的值。当堆栈帧(以及因此*tileCoordinate
)在函数返回时超出范围时,该指针将不再存在。
但是,因为您将指针值返回给调用函数,它现在存在于当前堆栈帧中(返回后)。该值由变量*currentTilePosition
引用。
malloc()
分配的内存是一个完全不同的故事;堆上存在动态分配的内存。您应释放在执行分配的同一实现中分配的任何内存。这意味着一旦您使用free()
,就会在currentTilePosition
上调用{{1}},通常是在同一个文件中。
答案 2 :(得分:3)
要遵循的非常基本的规则是,如果你返回一个* malloc * ed指针,或者给用户一个函数将指针传递回来进行释放,或者记录你* malloc * ed它并且它们应该释放它。
我已经看到了各种各样的解决方案(包括完整的内存管理抽象),我个人更喜欢API指定的免费方法,因为当需要释放对象并且它提供API时,它很清楚该怎么做最后一次尝试进行任何额外的清理工作。
答案 3 :(得分:3)
调用者需要free
您的函数指针malloc
。
但是,如果将tileForCoordinates
函数打包到动态库中,则还应提供一个用于释放内存的附带函数,而不是让调用者执行此操作。这是因为调用者可能以与库不同的方式链接到C运行时。例如,如果您的库静态链接到C运行时,而调用者动态链接到它,反之亦然,让调用者释放内存将导致崩溃。在这种情况下,您可以提供类似于以下的功能:
void freeTileCoordinates( CGPoint **tileCoordinate )
{
// Also add additional checks for NULL pointer
free( *tileCoordinate );
*tileCoordinate = NULL;
}
使用示例:
CGPoint *point = tileForCoordinates( ... );
// use point
...
// now free it
freeTileCoordinates( &point );
答案 4 :(得分:1)
作为一项规则,您malloc
所需要的所有内容free
。作为另一个规则,如果您的api进行了分配,那么您的api也应该进行解除分配,因为在未来的某个时间点,您可能会改变基础机制。此外,在Windows中,如果内存是由DLL分配的,则必须使用相同的DLL释放内存或发生崩溃的事情。
因此,一般来说,模式看起来像这样:
MyType* foo = myapi_dosomething(x,y,z);
if (!foo) die("No Foo!");
use_object(foo);
myapi_free(foo);
foo=NULL; // just in case