2010-04-27 18 views
0

我有一個小的VC++應用程序,分爲兩部分。第一部分包含主要功能,並編譯爲靜態庫。第二部分是從第一部分鏈接到圖書館的Windows服務。從無關庫對象中腐蝕靜態變量(反之亦然)

我看到一些由內存損壞引起的奇怪行爲。通過設置數據斷點等,我可以確定每次從一個庫對象中的某些成員寫入兩個時,服務片中的靜態變量正在被破壞。相反,當靜態變量指向的位置被寫入時,庫對象的成員會被破壞。會不會有物體重疊?

編輯:我忘了提及BlahHelper的實例是在我的服務代碼在全球範圍內。這支持重疊理論,因爲BlahHelper和ServiceBase :: m_service都應該在exe的全局數據區域中。

EDIT2:通過查看原始內存並檢查所有相關對象的地址,我已確認BlahHelper對象與ServiceBase :: m_service指針重疊。爲什麼會出現這種情況?

這裏有感興趣的類定義:

// This is the basis of my service. I derive from this and override 
// the start() and stop() methods to implement the service. 
class ServiceBase 
{ 
public: 

    virtual ~ServiceBase(); 

    static void Run(ServiceBase& service); 

protected: 

    ServiceBase(DWORD controlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE | 
             SERVICE_ACCEPT_STOP | 
             SERVICE_ACCEPT_SHUTDOWN); 

    virtual void Start(DWORD control) = 0; 
    virtual void Stop(DWORD control) = 0; 

    void UpdateState(DWORD state, 
        HRESULT errorCode = S_OK); 

    const std::wstring& ServiceName() const; 

private: 

    void SetServiceStatus(); 

    static void WINAPI ServiceMain(DWORD argumentCount, 
            PWSTR* arguments); 

    static void WINAPI Handler(DWORD control); 

    static ServiceBase* m_service; // This is being corrupted 
    SERVICE_STATUS_HANDLE m_handle; 
    ServiceStatus m_status; 
    std::wstring m_serviceName; 

}; 

這是在庫中的類之一。當我將庫鏈接到我的服務exe文件並實例化一個BlahHelper對象時,我發現了一些內存損壞的奇怪問題。

// Writing to _blah2Open or _blah1Open causes corruption of ServiceBase::m_status 
class BlahHelper 
{ 
    // Names changed to protect the innocent 
public: 
    BlahHelper(); 
    ~BlahHelper(); 

    HRESULT GetSomeInfo(); 
    HRESULT GetSomeStatus(LPWORD statPosition); 

    void Init(char blah1Sp[], char blah2Sp[], HWND messageWindow); 
    bool Blah1ConnectionOpen(){return _blah2Open;}; 
    bool Blah2ConnectionOpen(){return _blah1Open;}; 
    hash_map<string,short> GetSomeJunk(){return _someJunk;}; 
    void Refreshblah1Config(); 
    bool HasItemsTakenSensor(){return _blah1HasItemsTakenSensor;}; 
    void Enterblah2(); 
    void blah2Exited(); 
    void Ackblah2ExitReq(); 
    void Cleanup(); 
    void Initblah1(); 
    void Initblah2(); 

private: 

    LPWFSRESULT OpenSession(char* spName, HSERVICE* handle); 
    LPWFSRESULT Getblah1Caps(); 
    void Cleanupblah1(); 
    void Cleanupblah2(); 
    void Closeblah1(); 
    void Closeblah2(); 
    void Openblah1(); 
    void Openblah2(); 
    void Registerblah1(); 
    void Registerblah2(); 
    void Checkblah1Caps(); 
    void CheckSomeJunk(); 
    void Getblah1Config(); 
    void LogMessage(string message, int logLevel); 

    char* _SpName1; 
    char* _SpName2;   
    HWND _messageWindow;  
    HSERVICE _Handle1;  
    HSERVICE _Handle2;  
    bool _blah2Open;    // writing to this causes corruption of ServiceBase::m_service 
    bool _blah1Open;    // writing to this causes corruption of ServiceBase::m_service 
    const string _logSource; 
    const int _logMsgId; 
    bool _blah1HasItemsTakenSensor; 

    hash_map<string, short> _someJunk; 
}; 

正如我所說的,一個數據斷點透露,寫_blah1Open或_blah2Open腐化ServiceBase :: m_service。作爲進一步的確認,我評論了BlahHelper的每一行實現這些價值的信息,腐敗消失了。

如果我更改BlahHelper成員聲明的順序,我仍然看到內存損壞問題,但症狀會改變。

如果我直接將庫代碼包含在服務中,我不會再看到這個問題了。除了診斷目的,我無法做到這一點,但它確實表明在鏈接過程中發生了一些奇怪的事情。

另外需要注意的是,該庫是使用Muli-Byte字符集進行編譯的,而鏈接該庫的服務應用程序則使用Unicode進行編譯。這將很難改變。

任何人都可以提出可能的原因爲什麼這可能會發生,或方法來診斷問題?當我意識到自己有內存損壞時,我希望得到一個簡單的原因(如緩衝區溢出)。但是,我不知道爲什麼一個對象會像這樣踩到另一個對象。

回答

1

你的意思是說m_service本身發生了變化,或者* m_service發生了變化?

如果您檢查& _blah2Open和m_service的地址是否匹配?

(記住_blah2Open是一個變量,m_service是一個指針,所以要_blah2Open的地址和m_service的值)

_blah2Open的地址綁定到是對堆或疊層,分配爲是CBlahHelper的一部分,所以這個地址不太可能指向m_service的內容。

如果它的內容的情況下,在由m_service變化指出, 一種可能的情況是: m_service在代碼中某處初始化,但由於某些原因靜態初始化不被稱爲你的情況,所以m_service點某處隨機並且當某個對象在那裏被分配時,內容會被覆蓋。 您需要在程序運行的最開始處放置數據斷點,並跟蹤m_service每次更改的時間。

在另一方面,如果你說m_service和_blah1Open必須在故障點的同一地址: 兩個不同的變量(不是工會內)總是有不同的地址,所以沒有邏輯的情況下兩個m_service和_blah2Open在內存中共享相同的地址。這意味着編譯器生成的代碼基本失敗,這是非常不可能的....

+0

m_service本身發生變化。另外,m_service的初始化會影響_blah1Open和_blah2Open。 下面是一些存儲器地址以及大小。在運行時: &m_service:0x0053db84大小:4 &_blah1Open:0x0053db86大小:1 &_blah2Open:0x0053db85大小:1 &_blah1Handle:0x0053db83大小:2 &_blah2Handle:0x0053db81大小:2 正如你所看到的,_blah1Open和_blah2Open位於m_service的最後2個字節。 – Odrade 2010-04-27 15:38:08

0

由於這兩個部分是用不同的選項編譯的,你是否檢查過從每個模塊的角度來看sizeof(BlahHelper)是一樣的?編譯選項可能會導致結構佈局看起來不同,從而導致內存重疊。否則,我無法看到BlahHelper的成員覆蓋statc指針的任何方式。

+0

我開始懷疑這可能是這種情況。我會檢查它。 – Odrade 2010-04-27 15:38:55

+0

據我所知,兩個模塊的大小是相同的。我可能做了錯誤的決定。 – Odrade 2010-04-27 15:56:39

+0

我調試到服務中,然後從即時窗口執行sizeof(XfsHelper)。我將.lib更改爲.exe編譯,然後在那裏執行主函數。然後,作爲額外的嘗試,我將一個GetBlahHelperSize方法添加到.lib中並從服務中調用它。所有的結果都一樣。 – Odrade 2010-04-27 15:58:02

相關問題