2009-08-24 7 views
5

mio C# applicazione mi manda una traccia dello stack quando viene generata un'eccezione non gestita, e sto guardando uno, ora che non capisco.Puoi spiegare questo bizzarro crash nel runtime .NET?

Sembra che questo non possa essere colpa mia, ma di solito quando penso che in seguito mi sono sbagliato. 8-) Ecco la traccia dello stack:

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 

Quindi il mio codice (i nomi delle funzioni offuscati alla fine) chiama System.IO.Directory.GetFiles(path) che blocca con un problema stringa di indicizzazione.

Purtroppo non so il valore di path che è stato passato in, ma a prescindere che, sicuramente non dovrebbe essere possibile per System.IO.Directory::GetFiles crash del genere? Prova come potrei non riuscire a trovare alcun argomento a GetFiles che riproduce l'arresto anomalo.

Sono davvero guardando un bug nel runtime .NET, o c'è qualcosa che potrebbe legittimamente causare questa eccezione? (Ho potuto capire le cose andare male se la directory è in corso di modifica, al momento ho chiamato GetFiles, ma non mi aspetto un'eccezione indicizzazione stringa in questo caso.)

Edit: Grazie a tutti per i loro pensieri! La teoria più probabile è che ci sia un pathname con caratteri dodgy non-BMP Unicode, ma non riesco ancora a farlo. Guardando il codice in GetFiles con Reflector, penso che l'unico modo in cui si può rompere è per GetDirectoryName() per tornare un percorso che è più rispetto al suo ingresso, anche quando il suo ingresso è già completamente normalizzata. Bizzarro. Ho provato a fare i nomi di percorso con caratteri non BMP in (non ho mai avuto una directory chiamata {Simbolo musicale G CLEF} prima 8-), ma non riesco ancora a farlo rompere.

Quello che ho fatto è aggiungere la registrazione aggiuntiva intorno al codice mancanza (e hanno fatto sì che la mia registrazione funziona con caratteri non BMP!). Se succede di nuovo, avrò molte più informazioni.

+0

Forse sta cercando di guardare una directory con nomi di file corrotti? –

+1

Qual è il valore del parametro in System.IO.Directory::GetFiles(String path) + 0? – Yakeen

+0

La tua applicazione incorpora un codice nativo? –

risposta

0

Forse ha qualcosa a che fare con l'obfuscator. E l'obfucatore mette le cose a posto. Prova a eseguire il codice senza l'offuscatore. E pubblica i tuoi risultati.

modifica: Sei in grado di riprodurre l'incidente?

+0

... non conosce l'input che ha causato l'eccezione. – JoshJordan

+0

@Henri: Lo stesso codice offuscato sta funzionando bene per tutti gli altri - c'è solo un cliente con il crash. Non penso che l'obfuscator sia pertinente. Tutto ciò che sta facendo è passare una stringa su GetFiles - come potrebbe l'oscuramento rovinare tutto? Cool e no, non sono in grado di riprodurre l'incidente. – RichieHindle

+0

L'offuscamento può fare alcune cose strane al codice .NET. Se l'obfuscator fa cose come l'iniezione di codice falso e simili, la logica del programma non è più esattamente la stessa di prima dell'offuscamento. Ho la sensazione che stia facendo qualcosa per manipolare quell'input di stringa. Potresti vedere se è possibile escludere quella funzione dall'offuscamento e vedere se questo corregge il problema. – Navaar

1

Solo una supposizione ... alcuni nomi di file sono passati come argomenti più lunghi di 256 caratteri? Lo standard .Net standard Le funzioni System.IO non possono gestire un nome di file più lungo di quello.

+0

Mi dispiace - questo genererebbe un PathTooLongException, non il tuo errore. –

+0

@Matt: Questo è qualcosa a cui non avevo pensato, ma penso che tu abbia ragione, darebbe l'ovvia eccezione, non uno strano. Ho passato molto tempo cercando di rompere 'GetFiles' dandogli argomenti rotti, e invariabilmente mi restituisce un'eccezionale eccezione. – RichieHindle

+0

Ho controllato la documentazione ufficiale (come sono sicuro che tu abbia) e ArgumentOutOfRangeException non è nemmeno elencata tra le eccezioni che questa funzione può generare. L'unica cosa anche lontanamente vicino che posso pensare sarebbe un carattere jolly o forse un percorso relativo che ha bisogno di espansione - qualsiasi dato che deve essere espanso per fare un percorso assoluto, come indicato da Lucas. –

2

Si può provare a guardare nel codice per System.IO.Path.GetFiles() con .NET Reflector. Da un rapido sguardo apparentemente chiama solo String.Substring() per dividere qualcosa dalla fine del percorso e lo aggiunge di nuovo vicino alla fine del metodo. Controlla Path.DirectorySeparatorChar (il backslash, '\') e Path.AltDirectorySeparatorChar (la barra, '/') per determinare l'indice e la lunghezza della sottostringa.

La mia ipotesi sarebbe che i nomi di file o cartelle non validi o unicode confondono il metodo.

+0

@Lucas: Sembra che l'unico modo in cui può interrompersi sia per 'GetDirectoryName()' per restituire un percorso più lungo del suo input, anche quando il suo input è già completamente normalizzato. Bizzarro. E non riesco a trovare un percorso che lo faccia accadere. – RichieHindle

1

Wow .. Io non credo che sia mai successo a me.

Stai dicendo che è solo questo un cliente che questo succede?

  1. Potrebbe voler avviare la registrazione dei parametri del percorso e impostare il programma per l'invio dei registri per l'analisi, ritengo che il problema sia nel formato dell'argomento.
  2. Se questo codice offuscato viene creato dal proprio obfuscator, perché non provare a testarlo sulla propria macchina 'non-offuscato' con alcuni dei parametri raccolti e vedere il risultato?
  3. Non c'è nulla nello spazio dei nomi Path, come Path.Exist() o Path.IsValid() per dare al parametro un controllo .. forse c'è un buffo '/' o '\' e altri caratteri, quindi quando il l'API interna analizza ciascun componente, c'è qualche tipo di corruzione nel determinare ogni porzione della stringa del percorso a causa di caratteri divertenti? Solo un'osservazione, dato che la Sottostringa sta fallendo.

Spero che ti aiuti e buona fortuna! Per favore fateci sapere qual è la soluzione che avete trovato, poiché sarà sicuramente interessante.

+0

@Leo: 1. Più registrazione, sì, già fatto per la prossima versione. 8-) 2. Lo farà. 3. 'GetFiles' si protegge già da tutto questo - vedi il mio commento alla risposta di Matt http://stackoverflow.com/questions/1324806/can-you-explain-this-bizarre-crash-in-the-net-runtime/1324846 # 1324846 – RichieHindle

1

Forse potresti fornire alcuni dettagli sul problema del cliente. Cose come: 1. Nome del sistema operativo e versione 2. Lingua del sistema operativo 3. Nella versione .Net che si sta utilizzando, la versione .Net del cliente è in esecuzione.

Ci potrebbero essere caratteri unicode nel percorso della directory che causano la disattivazione della lunghezza della stringa di uno o più.

Un'altra nota: il testo di eccezione suggerisce che il programma è stato scritto in C++ gestito. Non stai mescolando in nessuna manipolazione di stringhe non gestite, vero?

Potrei suggerire che, se è possibile, modificare la diagnostica per acquisire la variabile di percorso effettiva che causa l'errore. Una spiegazione plausibile possibile: http://support.microsoft.com/kb/943804/

+0

@Joe: XP-32 SP3, inglese, 2.0, 2.0.50727.1433 (i commenti di Earwicker sono 3.5 senza SP1). È tutto C# (la sintassi simile a C++ nella traccia dello stack è perché sono formattati dal mio codice, e sono più di un ragazzo C++ che di un ragazzo C# 8-) – RichieHindle

+0

Tecnicamente, 2.0.50727.1433 è 2.0 SP1 . È possibile ottenere 2.0 SP1 aggiornando l'installazione 2.0 o installando 3.5 (senza SP1), che installa 2.0 SP1 e 3.0 SP1 come prerequisiti. – Lucas

1

La prima e unica domanda avrebbe dovuto essere: "Esegui ChkDsk?"

0

Non sono sicuro che ciò sia correlato, ma sto utilizzando GetFiles in Visual C++, provocando un arresto anomalo durante l'elencazione del contenuto di C :, ho avuto una cartella con autorizzazioni incasinate da un'installazione precedente. Ho reclamato la cartella al mio attuale utente e ha risolto il crash.

+0

@ Gavin: Sai qual è stata l'eccezione? – RichieHindle

0

Dalla souce e dai commenti, ho il sospetto che un percorso UNC stia causando problemi, con una possibile autorizzazione di sicurezza o un problema di autorizzazione di condivisione. Ad esempio, se l'utente ha disattivato la creazione di nomi di file 8.3, si avranno sicuramente problemi di percorso UNC perché causano il fallimento del provider di rete nel recupero dei nomi file appropriati in Windows 2000 e Windows XP. (Dimentico quali service pack questo bug era corretto)

Di seguito è riportato il codice sorgente di importanza.

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

E 'una possibilità di codificare rapidamente una console app ed eseguirlo in modalità debug. In pratica passa attraverso l'intera directory di file usando il metodo GetFiles. Forse qualcosa colpirà e dovresti essere in grado di localizzare rapidamente il file incriminato?

+0

Succede sempre solo sulla macchina di un cliente, quindi il cliente avrebbe dovuto farlo. A mia conoscenza non è successo di nuovo, quindi forse AMissico aveva ragione con il suo suggerimento ChkDsk. – RichieHindle

Problemi correlati