記憶體那些事之野指標

來源:互聯網
上載者:User

       在稍大點的軟體工程中,我們經常需要用到基於介面的回調在達到模組解耦/通訊的目的.甚至在超大的工程中,類似這樣的回調機制比如委託(Delegate)會成為系統重要的基礎組件,為分模組的系統開發提供良好的底層支援.

       但是隨著這樣的機制被大量使用,指標的生命週期管理,迴圈重入等問題導致野指標的問題就越來越突出,極大的破壞了軟體的穩定性,造成業務的損失.本文重點探討提供一種機制,把這種情況下野指標的危險降到最低.

       首先我們看一種典型的應用情境.socket模組通常需要通知外部模組一些資訊,比如收包,連錯錯誤/成功之類的.一般會有如下調用;

       pISocket->setSocketSink(pSocketSink);

       這裡設定了回調後,如果指標的生命週期管理失當,就會形成野指標而宕機.實際應用中可能情況更複雜.比如典型的 mmorpg中,模組能達到幾十個.他們的互動(更多的是基於委託)會更加頻繁和複雜,出問題的可能性會大很多.

       為了能夠讓所有有儲存指標的模組能感知到指標的失效,需要把回調指標再包一層.這個額外的中介層,主要包含以下三個參數:

template<class clsSink>

class SafeHandle

{

clsSink* m_pSink;

//回調指標.

int* m_refCount;

//引用計數,控制所有引用同一個指標的控制代碼相關動態申請變數的生存周期

bool* m_isValid;

//一旦無效,可以讓所有引用該指標的控制代碼都無效..

}

再讓回調介面繼承以下介面:

template<class clsSink>

class ISafeSink

{

public:

typedef SafeHandle<clsSink> SinkSafeCls;

private:

SinkSafeCls m_safeHandle;

public:

ISafeSink()

{

m_safeHandle.setNewSink(static_cast<clsSink*>(this));

}

~ISafeSink(){ m_safeHandle.setValid(false);}

const SinkSafeCls& getSafehandle() { return m_safeHandle;}

};

對於回調指標而言,如下繼承即可:

class ISimple   : public ISafeSink<ISimple>

{

};

        這裡雖然解決了野指標問題,但是對於安全回調和非安全的,使用這套東西的人卻需要不同的編碼.即 前者儲存的是SafeHandle<clsSink>,後者直接儲存回調指標.為了保持一致性,讓外部使用者不用關心回調的實現細節.我們需要做更深一層的封裝.

          我們首先需要做的根據回調介面是否有繼承自ISafeSink,定義/擷取不同的類型。再把

SafeHandle操作符重載.讓SafeHandle<clsSink>跟單獨的回調指標具有相同的外部調用邏輯.其中 判斷是否有繼承關係的類大概如下:

template<class Base,class Derived>

class IsDerived

{

struct char2 { char c[2];};

static Derived& makeDerived();

static char test(...);

static char2 test(const Base&);

typedef  SaveType<sizeof(test(makeDerived()))==sizeof(char) ? 1 : 0,  Derived>   HelperType;

};

我們使用這個回調實現的話,如下調用即可

class testClass

{

SavePtrThis<ISimple>::PtrType m_safeSink;

public:

void addSink(ISimple * p)

{

m_safeSink =  SavePtrThis<ISimple>::FuncType::get_ptr(p);

}

void run()

{

if(!m_safeSink)

{

printf("控制代碼非法..\n");

return;

}

m_safeSink->testFunc();

}

 };

 

 最後附上單元測試的代碼,在VC9及gcc 4.4編譯通過

  http://kevincodelib.googlecode.com/files/SafeSink.zip

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.