處理由引用計數引起的洩漏

2021-09-06 07:07:39 字數 2378 閱讀 8727

網遊伺服器的邏輯一般來說比較複雜,而且在很多情況下還使用了多執行緒,因此使用基於引用計數的智慧型指標能很大程度的減少記憶體洩漏和物件失效等問提.

但是基於引用計數的指標在很多情況下也會產生另一種情況的洩漏,例如:網遊中有乙個代表角色的型別character,角色的物件在網遊中可以說是最常見的物件

之一了,與幾乎所有的遊戲邏輯都有關係,因此,乙個角色物件可能會存在於很多容器,或被其它的物件所持有,為了保證角色物件的有效性,常常會使用基

於引用計數的智慧型指標來存放角色物件。問題由此產生了,例如當乙個角色離開地圖,我們就需要把所有指向這個角色的智慧型指標清0,稍有不甚,漏掉乙個都

會導致資源無法釋放,而且要找到具體還被哪些地方持有是相當麻煩的事情.

在我們專案中,處理這種情況的做法是,不使用智慧型指標來存放物件,而是採用了另外一種叫做ident的物件.物件被建立之後,只由乙個容器持有其原始物件,

其它的所有外部引用持有的都是那個由原始物件產生的ident對像.當邏輯需要使用原始物件時,通過ident轉換成原始物件,如果原始物件依舊有效則返回原始

物件,否則,返回null。

首先,原始物件是基於引用計數的物件,其中有乙個64位的identity成員,其高32位是乙個全域性計數器的值,低32位是乙個時間戳.物件被建立的時候,

identity被正確的初始化,

被銷毀時將identity置0,這樣,兩個物件identity擁有相同值的概率是相當低的.

然後看下ident物件,只有一備份的identity和乙個指向原始物件的指標,通過make_ident函式,可以通過乙個原始物件的指標產生乙個ident物件.

然後,

可以通過cast_2_refbase將乙個ident物件轉換回原始指標,如果轉換成功,原始物件的引用加1,防止物件正在使用的時候被其它執行緒釋放掉.只要在

使用完畢後呼叫

ref_decrease清理即可.

refbase.h

#ifndef _refbase_h

#define _refbase_h#include

#include

#include

#include

#include

"atomic.h

"extern

atomic_32_t global_counter;

struct

refbase

;void ref_init(struct refbase *r,void (*destroyer)(void*),int32_t initcount);

static inline atomic_32_t ref_increase(struct refbase *r)

static inline atomic_32_t ref_decrease(struct refbase *r)

else

; nanosleep(&ts, null);}}

r->destroyer(r);

}return

count;

}typedef

struct

ident

ident;

static inline ident make_ident(struct refbase *ptr)

;

return

_ident;

}static

inline ident make_empty_ident()

;

return

_ident;

}static inline struct refbase *cast_2_refbase(ident _ident)

}return

null;

}static

inline int32_t is_vaild_ident(ident _ident)

#define to_ident(other_ident) (*(ident*)&other_ident)

#endif

refbase.c

#include "

refbase.h

"#include

"systime.h

"atomic_32_t global_counter = 0

;void ref_init(struct refbase *r,void (*destroyer)(void*),int32_t initcount)

大致處理邏輯如下:

ident _ident;

struct ref_base *atker = cast_2_refbase(_ident);

if(atker)

else

Python中的引用計數

為了跟蹤記錄已經分配的記憶體,python 做法類似於撲克牌遊戲中的記牌手法。乙個物件在建立時被加上乙個引用。乙個內部的引用記錄變數將跟蹤記錄下每個物件有多少個引用。乙個物件被建立和被賦值時,它的初始引用計數為 1。物件新的引用也叫別名 alias 發生在 其他變數也被賦值到同乙個物件 物件作為呼叫...

獲取核心物件的引用計數

正規的方法可以用 zwqueryobject 但是該函式用起來比較麻煩。事實上還有乙個方便的函式 void obreferenceobject in pvoid object return value obreferenceobject returns a value that is reserve...

引用計數的寫時拷貝

首先我們需要知道什麼是寫時拷貝,通俗的說,就是寫的時候再拷貝。那到底什麼才是寫時拷貝呢?舉乙個很簡單的例子,就是建立乙個string類的物件,然後用這個物件再拷貝出多個物件,當然指標也會拷貝過去,造成多個物件指向同一塊空間,當對某個物件進行讀操作時,不會發生什麼問題,但當需要對某個物件進行寫操作時,...