2009-07-31 53 views
2

我們必須通過COM +運行在Windows 2003服務器上的本地C++應用程序。我最近在事件查看器注意到,其拋出異常,特別是異常C0000005,其中,根據http://blogs.msdn.com/calvin_hsia/archive/2004/06/30/170344.aspx意味着進程試圖寫入內存而不是它的地址空間內,又名訪問衝突。如何讀取調用堆棧?

在事件查看器中的條目提供了一個調用堆棧:

LibFmwk UTIL_GetDateFromLogByDayDirectory(字符常量*,類utilCDate &)+ 0xa26c LibFmwk UTIL_GetDateFromLogByDayDirectory(字符常量*,類utilCDate &)+ 0x8af4 ! LibFmwk!UTIL_GetDateFromLogByDayDirectory(字符常量*,類utilCDate &)+ 0x13a1 LibFmwk!utilCLogController :: GetFLFInfoLevel(無效)常量+ 0x1070 LibFmwk!utilCLogController :: GetFLFInfoLevel(無效)常量+ 0x186

現在

,據我所知,它給我的方法名去看看,但我得到一個感覺,在每行的末尾地址(例如+ 0xa26c)試圖將我指向該方法中的特定行或指令。

所以我的問題是:

  1. 有誰知道我可能會使用這個地址或任何其他信息在調用堆棧,以確定其翻倒在代碼中的哪條線路?
  2. 是否有任何資源在那裏,我可以讀更好地瞭解調用棧,
  3. 是否有任何免費/開源工具,可以在分析調用堆棧,幫助可能通過附加到調試符號文件和/或二進制?

編輯: 按照要求,在這裏,似乎是導致該問題的方法:由我們公司的一員

BOOL UTIL_GetDateFromLogByDayDirectory(LPCSTR pszDir, utilCDate& oDate) 
{ 
BOOL bRet = FALSE; 

if ((pszDir[0] == '%') && 
    ::isdigit(pszDir[1]) && ::isdigit(pszDir[2]) && 
    ::isdigit(pszDir[3]) && ::isdigit(pszDir[4]) && 
    ::isdigit(pszDir[5]) && ::isdigit(pszDir[6]) && 
    ::isdigit(pszDir[7]) && ::isdigit(pszDir[8]) && 
    !pszDir[9]) 
{ 
    char acCopy[9]; 
    ::memcpy(acCopy, pszDir + 1, 8); 
    acCopy[8] = '\0'; 

    int iDay = ::atoi(&acCopy[6]); 
    acCopy[6] = '\0'; 
    int iMonth = ::atoi(&acCopy[4]); 
    acCopy[4] = '\0'; 
    int iYear = ::atoi(&acCopy[0]); 

    oDate.Set(iDay, iMonth, iYear); 

    bRet = TRUE; 
} 

return (bRet); 

}

這是代碼寫在10年前這個人早已離開了,所以我並不想知道這是做什麼,但我確實知道它參與了將日誌目錄從「今日」重命名爲特定日期的過程,例如%20090329。操作符的數組索引,memcpy和地址確實使其看起來頗爲可疑。

我們似乎有另一個問題是,這只是發生在生產系統上,我們從來沒有能夠重現它在我們的測試系統或開發系統在這裏,這將允許我們附加一個調試器。

非常感謝! 安迪

+1

如果使用調試符號構建,您可能會得到實際的行號,而不是字節偏移量。 – 2009-07-31 11:07:00

+0

謝謝你指出。 – 2009-07-31 11:20:23

+0

那麼你確定傳入的pszDir至少有10個字符長嗎?如果情況並非如此,它肯定會崩潰。 – jussij 2009-08-04 01:05:25

回答

3

如果您確實需要將這些地址映射到您的函數 - 您需要使用.MAP文件並查看這些地址真正指向的位置。

但是在你的情況下,我寧願在調試器下調查這個問題(例如MSVS調試器或windbg)。作爲替代方案(如果客戶現場發生崩潰),您可以生成故障轉儲並在本地進行研究 - 可以通過Windows MiniDumpWriteDump API或SysInternals ProcDump實用程序(http://download.sysinternals.com/Files/procdump.zip)完成。

確保所有必需的符號文件都已生成並可用(還要設置Microsoft符號服務器路徑,以便Windows DLL的入口點也得到解決)。

恕我直言,這只是你需要的網站:http://www.dumpanalysis.org - 這是涵蓋所有問題的最佳資源。 請考慮看看這個PDF - http://windbg.info/download/doc/pdf/WinDbg_A_to_Z_color.pdf

1

點2和3被容易回答:

第三點。任何調試器。這就是他們所做的。設置你的調試器以解決這個特殊的異常。你應該能夠通過callstack點擊你自己,並找到堆棧上的不同調用(至少delphi可以做到這一點,所以視覺工作室也應該可以)。如果可能的話,不進行優化編譯。 OllyDBG也許可以工作 - 也許與其跟蹤功能相結合。

第二點。有關x86彙編程序,Reverseengineering的任何信息...嘗試:OpenRCE,NASM Documentation,ASM Community

第一點。 callstack告訴你這些函數。我不知道它是按順序寫的還是按相反的順序寫的 - 所以可能是第一行是最後一個被調用的函數或第一個被調用的函數。在調試器的幫助下跟隨呼叫。有時你可以在asm和代碼之間切換(取決於調試器,映射文件等)。如果您沒有源代碼 - 學習彙編程序,請閱讀逆向工程。閱讀您在第三方組件中調用的函數的文檔。也許你不滿足一個先決條件。

如果您能告訴更多關於PROGRAMM位(你有哪些源代碼的部分,是有關庫調用,......)


現在一些代碼閱讀:

該函數接受一個指向零終止的字符串的指針和對日期對象的引用。指針被認爲是有效的!

函數檢查字符串是否具有特定的格式(%,後跟8位數字,後面跟着\ 0)。如果不是這種情況,則返回false。這個檢查(big if)在沒有任何有效性檢查的情況下訪問指針。長度未被檢查,如果指針指向野外某處,則訪問此空間。我不知道較短的字符串是否會導致問題。它不應該因爲評估& &的方式。

然後在堆棧上分配一些內存。該字符串的數字部分被複制到它(這是正確的)並且緩衝區獲得其\ 0終止。阿託瓦提取數字。這將起作用,因爲使用了不同的起始位置和每個部分之後的\ 0終止。不知何故棘手,但很好。有些意見可以使一切都清楚。

然後將這些數字插入到對象中。它應該是有效的,因爲它是通過引用傳遞給函數的。我不知道你是否可以傳遞一個被刪除對象的引用,但如果是這樣的話,這可能也是你的問題。

無論如何 - 除了缺少字符串指針檢查外,此函數是有聲的,而不是問題的原因。這只是拋出異常的地方。搜索傳遞給此函數的參數。它們總是有效的嗎?做一些日誌記錄。

我希望我沒有犯任何重大錯誤,因爲我是Delphi程序員。如果我確實 - 隨時發表評論。

5

其他人都說過這句話,但沒有明確表示。看:

LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0xa26c 

的0xa26c偏移巨大,想辦法克服函數的結束。調試器顯然沒有LibFmwk的正確符號,所以它依賴於DLL導出並顯示相對於它能夠找到的最接近的偏移量的偏移量。

所以,是的,得到正確的符號,然後它應該是一件輕而易舉的事情。這裏UTIL_GetDateFromLogByDayDirectory沒有問題。