[英]Returning a malloc pointer
這里非常基本的問題,我對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返回的指針會發生什么? 它應該被釋放還是故事? :)
malloc()
聲明的指針將是當前正在執行的函數的堆棧幀中的值。 當堆棧幀(以及因此*tileCoordinate
)在函數返回時超出范圍時,該指針將不再存在。
但是,因為您將指針值返回給調用函數,它現在存在於當前堆棧幀中(返回后)。 該值由變量*currentTilePosition
引用。
通過所分配的存儲器 malloc()
是一個完全不同的故事; 堆上存在動態分配的內存。 您應釋放在執行分配的同一實現中分配的任何內存。 這意味着一旦你完成使用它就會在currentTilePosition
上調用free()
,通常是在同一個文件中。
你可以將tileCoordinate作為參數傳遞給函數調用嗎? 這樣,調用者就會發現更容易記住malloc / calloc和free。
要遵循的非常基本的規則是,如果你返回一個* malloc * ed指針,或者給用戶一個函數將指針傳遞回來以便釋放或者記錄你* malloc * ed它並且它們應該釋放它。
我已經看到了各種各樣的解決方案(包括完整的內存管理抽象),我個人更喜歡API指定的免費方法,因為它很清楚當釋放對象時它該做什么,它給了API最后一次嘗試做任何額外的清理工作。
調用者需要free
您的函數malloc
ed指針。
但是,如果將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 );
作為一項規則,一切你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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.