你能在.NET运行时解释这个奇怪的崩溃吗?

时间:2009-08-24 21:11:53

标签: c# .net debugging exception

我的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字符的路径名,但我仍然无法让它破裂。使用Reflector查看GetFiles中的代码,我认为唯一可以解决的方法是GetDirectoryName()返回更长的路径,即使输入是已完全正常化。离奇。我已经尝试用非BMP字符制作路径名(我从来没有一个名为{MUSICAL SYMBOL的目录) 在8-)之前的G CLEF}但我仍然无法让它休息。

我所做的是在失败的代码周围添加额外的日志记录(并确保我的日志记录与非BMP字符一起使用!)。如果它再次发生,我会有更多的信息。

9 个答案:

答案 0 :(得分:2)

您可以尝试使用.NET Reflector查看System.IO.Path.GetFiles()的代码。从快速查看,它显然只调用String.Substring()从路径的末尾拆分并将其添加回方法的末尾附近。它会检查Path.DirectorySeparatorChar(反斜杠,'\')和Path.AltDirectorySeparatorChar(斜杠,'/')以确定子字符串的索引和长度。

我的猜测是无效或unicode文件或文件夹名称会混淆方法。

答案 1 :(得分:1)

只是一个猜测......作为参数传递的任何文件名是否超过256个字符? .Net框架标准System.IO函数无法处理比该文件更长的文件名。

答案 2 :(得分:1)

哇..我不认为这件事发生在我身上。

你说这只是这一个客户吗?

  1. 可能要开始记录路径参数,并设置程序将日志发送给您进行分析,我觉得问题的形式是参数。
  2. 如果这个混淆的代码是从你自己的混淆器创建的,为什么不尝试在你的机器上测试它'未混淆'并收集一些参数并查看结果?
  3. Path命名空间中没有任何内容,比如Path.Exist()或Path.IsValid()给参数一个检查..也许有趣的'/'或'\'和其他字符,所以当内部API解析每个组件,由于有趣的字符,在确定路径字符串的每个部分时存在某种损坏?只是一个观察,因为子串失败。
  4. 希望有所帮助,祝你好运!请告诉我们您找到的解决方案是什么,肯定会是一个有趣的解决方案。

答案 3 :(得分:1)

也许您可以提供有关客户遇到问题的一些详细信息。像: 1.操作系统名称和版本 2.操作系统语言 3.您要定位的.Net版本,与客户运行的.Net版本相比。

目录路径中可能有unicode字符导致字符串长度偏离一个或多个。

另一个注意事项:异常文本表明您的程序是用托管C ++编写的。你不是在混合任何非托管字符串操作吗?

我可能会建议您,如果可以,修改诊断程序以捕获导致错误的实际路径变量。 可能的合理解释:http://support.microsoft.com/kb/943804/

答案 4 :(得分:1)

首先也应该唯一的问题是,“你的奔跑ChkDsk吗?”

答案 5 :(得分:0)

也许它与混淆器有关。然后,食物会搞砸了。尝试在没有混淆器的情况下运行代码。并发布您的结果。

修改 你能重现崩溃吗?

答案 6 :(得分:0)

不确定这是否相关,但我在Visual C ++中使用GetFiles,在列出C:的内容时崩溃了,原来我有一个文件夹,其中包含先前安装的混乱权限。我将文件夹重新收回给当前用户,并修复了崩溃。

答案 7 :(得分: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); 

答案 8 :(得分:0)

是否可以快速编写控制台应用程序并在调试模式下运行它。基本上使用GetFiles方法遍历整个文件目录。也许某些东西会被击中,你应该能够快速定位有问题的文件吗?