2009-08-24 65 views
5

當C#應用程序拋出一個未處理的異常時,它會向我發送一個堆棧跟蹤,現在我正在看一個我不明白的異常。你可以在.NET運行時解釋這種奇怪的崩潰嗎?

看起來好像這不可能是我的錯,但通常當我認爲我後來被證明是錯誤的。 8)這裏的堆棧跟蹤:

mscorlib caused an exception (ArgumentOutOfRangeException): startIndex cannot be larger than length of string. 
Parameter name: startIndex 
    System.String::InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy) + 6c 
    System.String::Substring(Int32 startIndex) + 0 
    System.IO.Directory::InternalGetFileDirectoryNames(String path, String userPathOriginal, String searchPattern, Boolean includeFiles, Boolean includeDirs, SearchOption searchOption) + 149 
    System.IO.Directory::GetFiles(String path, String searchPattern, SearchOption searchOption) + 1c 
    System.IO.Directory::GetFiles(String path) + 0 
    EntrianSourceSearch.Index::zz18ez() + 19b 
    EntrianSourceSearch.Index::zz18dz() + a 

所以我的代碼(在末尾的模糊函數名)調用System.IO.Directory.GetFiles(path)與一個字符串索引問題崩潰。

不幸的是,我不知道path的價值,但不管如何,System.IO.Directory::GetFiles肯定不應該像這樣崩潰?嘗試我可能不能拿出GetFiles重現崩潰的任何論據。

我真的在看.NET運行時的錯誤,還是有什麼可以合法地導致這個異常? (我能理解,如果該目錄是在我打電話GetFiles時間而改變的東西去錯了,但我不希望在這種情況下,一個字符串索引除外)。

編輯:感謝大家對他們的想法!到目前爲止,最可能的理論是,它有一個路徑名,其中包含非BMP的非Unicode字符,但我仍然無法讓它斷開。通過使用Reflector查看GetFiles中的代碼,我認爲它可以中斷的唯一方法是GetDirectoryName()返回的路徑是比其輸入長,即使其輸入已經完全標準化。離奇。我嘗試過使用非BMP字符製作路徑名(我在8-之前從來沒有一個名爲{MUSICAL SYMBOL G CLEF}的目錄),但我仍然無法讓它斷開。

我所做的是在失敗的代碼中添加額外的日誌記錄(並確保我的日誌記錄可以與非BMP字符一起工作!)。如果再次發生,我會獲得更多信息。

+0

也許它試圖查看具有損壞的文件名的目錄? – 2009-08-24 21:16:32

+1

什麼是System.IO.Directory::GetFiles(String path)+ 0中的參數值? – Yakeen 2009-08-24 21:16:38

+0

您的應用程序是否包含任何本機代碼? – 2009-08-24 21:17:17

回答

0

也許它與混淆器有關。而obfucator把事情搞砸了。嘗試在沒有混淆器的情況下運行代碼。併發布你的結果。

編輯: 你能重現崩潰嗎?

+0

......他不知道導致異常的輸入。 – JoshJordan 2009-08-24 21:18:22

+0

@亨利:同樣的混淆代碼對其他人來說運行得很好 - 只有這個客戶在崩潰。我不認爲混淆器是相關的。它所做的只是將一個字符串傳遞給GetFiles--如何將混淆現象搞砸? 8-)不,我無法重現崩潰。 – RichieHindle 2009-08-24 21:29:04

+0

混淆可以爲.NET代碼做一些奇怪的事情。如果混淆器執行僞代碼注入等操作,則程序邏輯不再與混淆之前的程序邏輯完全相同。我有一種感覺,它正在做一些操作該字符串輸入。您可能會看到是否可以從混淆中排除該功能,並查看是否可以解決問題。 – Navaar 2009-08-24 21:34:10

1

只是一個猜測......是作爲參數傳遞超過256個字符的任何文件名? .Net框架標準System.IO函數不能處理比​​這更長的文件名。

+0

對不起 - 這會產生一個PathTooLongException,而不是你的錯誤。 – 2009-08-24 21:23:28

+0

@Matt:這是我沒有想到的,但我認爲你是對的,它會給出明顯的例外,而不是一個奇怪的例外。我花了很長時間試圖通過給它打破參數來破壞'GetFiles',並且它總是拋出一個明智的例外回到我身上。 – RichieHindle 2009-08-24 21:28:22

+0

我檢查了官方文檔(我敢肯定你有),並且ArgumentOutOfRangeException甚至沒有被列爲這個函數可以拋出的異常之一。唯一能夠遠程關閉的東西我能想到的將是通配符,或者可能是需要擴展的相對路徑 - 任何需要擴展以形成絕對路徑的數據,就像盧卡斯指出的那樣。 – 2009-08-25 14:15:37

2

您可以嘗試使用.NET Reflector來查找System.IO.Path.GetFiles()的代碼。從快速查看它顯然只調用String.Substring()從路徑的末尾分開一些東西,並將其添加回到方法的結尾附近。它檢查Path.DirectorySeparatorChar(反斜槓,'\')和Path.AltDirectorySeparatorChar(斜槓,'/')以確定子串的索引和長度。

我的猜測是無效或unicode文件或文件夾名稱混淆該方法。

+0

@Lucas:看起來它唯一可以中斷的方式是GetDirectoryName()返回一個比它的輸入長的路徑,即使它的輸入已經完全標準化了。離奇。我無法想出一個能夠實現這一目標的路徑名。 – RichieHindle 2009-08-27 07:39:58

1

哇..我不認爲這曾經發生在我身上。

你是說這只是這個客戶發生這種情況?

  1. 可能要開始記錄路徑參數,並設置程序發送日誌給你分析,我覺得問題是在參數的格式。
  2. 如果使用您自己的混淆器創建了這個混淆代碼,那麼爲什麼不嘗試在您的計算機上對其中一些參數進行「未混淆」測試,並查看結果?
  3. 路徑名稱空間中沒有任何內容,例如Path.Exist()或Path.IsValid()給參數一個檢查..也許有趣的'/'或'\'和其他字符,所以當內部API分析每個組件,由於有趣的字符,在確定路徑字符串的每個部分時會出現某種錯誤?只是一個觀察,因爲Substring失敗。

希望有所幫助,祝你好運!請讓我們知道您找到的解決方案是什麼,這絕對是一個有趣的解決方案。

+0

@Leo:1.更多日誌記錄,是的,已經爲下一個版本完成了。 8-)2.會做的。 3.'GetFiles'已經保護自己免受所有這些東西的影響 - 看到我的評論馬特的答案http://stackoverflow.com/questions/1324806/can-you-explain-this-bizarre-crash-in-the-net-runtime/1324846#1324846 – RichieHindle 2009-08-25 06:33:23

1

也許你可以提供一些關於有問題的客戶的細節。諸如: 1.操作系統名稱和版本號 2.操作系統語言 3.您正在實施的.Net版本與客戶正在運行的.Net版本。

目錄路徑中可能存在導致字符串長度被一個或多個字符關閉的unicode字符。

另一個注意:異常文本提示您的程序是用託管C++編寫的。你不混合任何非託管字符串操作?

我可能會建議,如果可以,請修改診斷以捕獲導致錯誤的實際路徑變量。 一個可能的解釋:http://support.microsoft.com/kb/943804/

+0

@Joe:XP-32 SP3,English,2.0,2.0.50727.1433(Earwicker的評論是3.5沒有SP1)。這完全是C#(堆棧跟蹤中的C++類語法是因爲它們是由我自己的代碼格式化的,而我更像是一個C++人員,而不是C#人員。) – RichieHindle 2009-08-25 06:36:29

+0

從技術上講,2.0.50727.1433是2.0 SP1 。您可以通過更新2.0安裝或通過安裝3.5(w/o SP1)獲得2.0 SP1,後者安裝2.0 SP1和3.0 SP1作爲先決條件。 – Lucas 2009-08-25 13:20:54

1

第一個也是唯一的問題應該是「讓你跑ChkDsk?」

0

不確定這是相關的,但我在Visual C++中使用GetFiles,當列出C:內容時崩潰了,事實證明我有一個文件夾具有上一次安裝的權限。我將文件夾收回到我當前的用戶,並修復了崩潰。

+0

@Gavin:你知道例外是什麼嗎? – RichieHindle 2009-09-23 08:44:19

0

從您的意見和觀點來看,我懷疑UNC路徑會導致問題,並且可能存在安全性權限或共享權限問題。例如,如果用戶關閉了8.3文件名的創建,您肯定會遇到UNC路徑問題,因爲它會導致網絡提供者在Windows 2000和Windows XP中檢索正確的文件名失敗。 (我忘記了哪個服務包修正了這個bug。)

以下是源代碼的重要性。

String tempStr = Path.InternalCombine(fullPath, searchPattern); 

    // If path ends in a trailing slash (\), append a * or we'll 
    // get a "Cannot find the file specified" exception 
    char lastChar = tempStr[tempStr.Length-1]; 
    if (lastChar == Path.DirectorySeparatorChar || lastChar == Path.AltDirectorySeparatorChar || lastChar == Path.VolumeSeparatorChar) 
     tempStr = tempStr + '*'; 

    fullPath = Path.GetDirectoryName(tempStr); 
    BCLDebug.Assert((fullPath != null),"fullpath can't be null!"); 

    String searchCriteria; 
    bool trailingSlash = false; 
    bool trailingSlashUserPath = false; 

    lastChar = fullPath[fullPath.Length-1]; 
    trailingSlash = (lastChar == Path.DirectorySeparatorChar) || (lastChar == Path.AltDirectorySeparatorChar); 

    if (trailingSlash) { 
     // Can happen if the path is C:\temp, in which case GetDirectoryName would return C:\ 
     searchCriteria = tempStr.Substring(fullPath.Length); 
    } 
    else 
     searchCriteria = tempStr.Substring(fullPath.Length + 1); 
0

是否有可能快速編寫控制檯應用程序並在調試模式下運行它。基本上使用GetFiles方法遍歷整個文件目錄。也許會有一些事情會發生,你應該能夠快速找到違規文件?

+0

它只發生在客戶的機器上,所以客戶必須完成它。據我所知,這並沒有再次發生,所以也許AMissico對他的ChkDsk建議是正確的。 – RichieHindle 2009-10-29 08:05:51

相關問題