Можете ли вы объяснить причудливый сбой во время выполнения .NET? - PullRequest
5 голосов
/ 25 августа 2009

Мое приложение C # отправляет мне трассировку стека, когда оно генерирует необработанное исключение, и я сейчас смотрю на одно, которое не понимаю.

Похоже, это не моя вина, но обычно, когда я думаю, что впоследствии я ошибался. 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, но я все еще не могу его сломать. Глядя на код в GetFiles с помощью Reflector, я думаю, что единственный способ, которым он может сломаться, - это GetDirectoryName(), чтобы вернуть путь, который на длиннее , чем его вход, даже когда его вход уже полностью нормализован. Bizarre. Я пытался создать пути с не-BMP символами в (у меня никогда не было каталога с именем {MUSICAL SYMBOL G CLEF} до 8-), но я все еще не могу сломать его.

Что я сделал, так это добавил дополнительную регистрацию вокруг ошибочного кода (и убедился, что моя регистрация работает с не-BMP символами!). Если это случится снова, у меня будет намного больше информации.

Ответы [ 9 ]

2 голосов
/ 25 августа 2009

Вы можете попробовать просмотреть код для System.IO.Path.GetFiles() с помощью .NET Reflector . При быстром взгляде он, очевидно, вызывает только String.Substring(), чтобы отделить что-то от конца пути, и добавляет его обратно в конец метода. Он проверяет Path.DirectorySeparatorChar (обратная косая черта, '\') и Path.AltDirectorySeparatorChar (косая черта, '/') для определения индекса и длины подстроки.

Я думаю, что недопустимые или unicode имена файлов или папок сбивают с толку метод.

1 голос
/ 01 сентября 2009

Первый и единственный вопрос должен был звучать так: «Запустили ли вы ChkDsk?»

1 голос
/ 25 августа 2009

Возможно, вы могли бы предоставить некоторые сведения о клиенте, имеющем проблему. Вещи как: 1. Название и версия ОС 2. Язык ОС 3. Версия .Net, на которую вы ориентируетесь, по сравнению с версией .Net, которую использует клиент.

В пути к каталогу могут быть символы Юникода, из-за которых длина строки может быть отключена одним или несколькими.

Еще одно примечание: текст исключения предполагает, что ваша программа была написана на управляемом C ++. Вы не вмешиваетесь в какие-то неуправляемые манипуляции со строками?

Я мог бы предложить, чтобы, если вы можете, измените свою диагностику, чтобы зафиксировать фактическую переменную пути, которая вызывает ошибку. Возможное правдоподобное объяснение: http://support.microsoft.com/kb/943804/

1 голос
/ 25 августа 2009

Ух ты ... Я не думаю, что это когда-либо случалось со мной.

Вы говорите, что это только один клиент, с которым это происходит?

  1. Возможно, вы захотите начать регистрацию параметров пути и настроить программу на отправку журналов вам для анализа, я чувствую, что проблема в формате аргумента.
  2. Если этот запутанный код создан из вашего собственного обфускатора, почему бы вам не попробовать протестировать его на своем компьютере «без запутывания» с некоторыми собранными параметрами и посмотреть результат?
  3. Нет ли в пространстве имен Path ничего, например Path.Exist () или Path.IsValid (), чтобы дать параметру проверку ... может быть, есть смешные '/' или '\' и другие символы, поэтому когда внутренний API анализирует каждый компонент, существует ли какая-то искажение при определении каждой части строки пути из-за забавных символов? Просто наблюдение, так как Подстрока не работает.

Надеюсь, что это помогает и удачи! Пожалуйста, дайте нам знать, какое решение вы нашли, поскольку оно определенно будет интересным.

1 голос
/ 25 августа 2009

Просто предположение ... передаются ли имена файлов в качестве аргументов длиннее 256 символов? Стандартные функции System.IO платформы .Net не могут обрабатывать имя файла, которое длиннее этого.

0 голосов
/ 29 октября 2009

Это возможность быстро закодировать консольное приложение и запустить его в режиме отладки. В основном перебирайте весь каталог файлов с помощью метода GetFiles. Может быть, что-то ударит, и вы сможете быстро найти поврежденный файл?

0 голосов
/ 07 октября 2009

Из источника и ваших комментариев я подозреваю, что путь UNC вызывает проблемы с возможным разрешением безопасности или проблемой с общим доступом. Например, если пользователь отключил создание имен файлов 8.3, у вас наверняка возникнут проблемы с UNC-путями, поскольку это приводит к сбою сетевого провайдера при получении правильных имен файлов в Windows 2000 и Windows XP. (Я забыл, в каких пакетах обновления эта ошибка была исправлена.)

Ниже приведен важный исходный код.

    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 голосов
/ 23 сентября 2009

Не уверен, что это связано, но я использую GetFiles в Visual C ++, он зависал при перечислении содержимого C :, оказалось, у меня была папка с испорченными разрешениями из предыдущей установки. Я вернул папку своему текущему пользователю, и она исправила сбой.

0 голосов
/ 25 августа 2009

Возможно, это как-то связано с обфускатором. И обфукатор все портит. Попробуйте запустить код без обфускатора. И опубликуйте свои результаты.

редактирование: Вы можете воспроизвести аварию?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...