2011-05-09 48 views
1

我的應用程序使某些工作的工人代理下面檢測不正確的堆棧變量使用

void Execute ProcessWork 
{ 
    int nRes = 0; 
    CFireProcessMessageWork *pProcessMessageWork = new CFireProcessMessageWork(); 
    // Incorrect use of stack variable 
    pProcessMessageWork->m_pStatus = &nRes; 
    // Worker Agency 
    m_pMessageWorkerAgency->SubmitWork(pProcessMessageWork); 
} 

給出CFireProcessMessageWork的定義如下線程池中的線程來執行。下面給出的類的DoWork方法將在工作線程中執行。由於變量nRes以不正確的方式使用,我的應用程序偶爾崩潰。我花了差不多一個星期的時間來找出問題的原因。我嘗試使用完整選項和堆棧幀(/ RTC)來檢測問題。但是應用程序在與該問題無關的位置崩潰。

有沒有microsoft提供的任何工具來檢測這些類型的問題?

class CFireProcessMessageWork 
{ 
public: 
    int *m_pStatus; 
public: 
    CFireProcessMessageWork() 
    { 
     m_pStatus = NULL; 
    } 
    int DoWork() 
    { 
    // Using Address of nRes 
     *mpStatus = 0; 
     // Do Some Work and Pass mpStatus to fill the error code 
     HRESULT hRes = pGEMMessageEvents->ProcessMessage(varData, m_nMsgCount, m_newTkt,m_idxFunc,&m_nRetVal); 
     return *mpStatus 
    } 
} 
+2

我不知道一個工具,但你肯定有一個*進程*到位 - 它被稱爲*代碼審查*! – Nim 2011-05-09 07:51:02

+0

爲什麼要在第一個地方存儲地址? – 2011-05-09 07:58:55

回答

3

問題是這些行中的每一行對編譯器都有意義。沒有什麼與他們錯了,只是組合不是很好。即使那樣,它也需要大量額外的工作和分析才能確定它是錯誤的用途。

舉個例子,你可以在同一個函數中加入工作線程,然後一切都會正確的,如果函數沒有在另一個線程中處理,而只是調用SubmitWork調用中的代碼,那麼它會是正確的...編譯器不一定知道線程,所以事實上編譯器幾乎不可能檢測到這一點。

另一方面,這對審稿人來說應該是非常明顯的,所以通過審閱代碼可以更好地解決問題。其他可能的選項將使用某種形式的共同所有權的處理,可呈現可能意味着更多的成本資源:

void Execute ProcessWork { 
    std::shared_ptr<int> nRes = std::make_shared<int>(0); 
    CFireProcessMessageWork *pProcessMessageWork = new CFireProcessMessageWork(); 
    pProcessMessageWork->m_pStatus = nRes;     // copies the shared_ptr 
     m_pMessageWorkerAgency->SubmitWork(pProcessMessageWork); 
} 

在這種情況下,共享對象的所有權在額外配置的成本,保證線程在更新狀態時不會導致未定義的行爲。但是,從語言的角度來看,雖然這會使程序正確,但它仍可能是不受歡迎的:在工作線程之外,狀態不會爲可讀的,因爲唯一的其他參考是外部的工作人員控制。

+0

羅德里格斯 - dribeas:你有我的+1非常ellaborate解釋:) – 2011-05-09 08:32:01

3

你被路過&nRes這裏寫語法上有效的代碼,但因爲它是在棧本地varaible,它是在其他線程被訪問,地址是不會有效,導致在崩潰。我認爲仔細的同行代碼審查應該有助於解決這些問題。