项目未标记为“首选32位”时读取文件头时出现AccessViolationException

时间:2014-06-02 20:13:51

标签: c# .net winapi

以下代码用于从文件头读取第一个字节。

在Windows 8 64bit上运行,此代码在标记为“AnyCPU - 首选32位”的项目下运行时有效。 (.NET 4.5.1)

如果它在'AnyCPU'下运行(未选中'Prefer 32 bit') - 它会抛出

  

“AccessViolationException:附加信息:尝试阅读   或写保护的内存。这通常表明其他   记忆已腐败。“

在以前的.NET版本中,它可以作为“AnyCPU”使用。

为什么“Prefer 32 bit”选中与否之间的行为不同?

为什么.net版本之间的行为有所不同?

public class FileParser
{
    private static uint _hLib;

    public static void Parse(string fileName)
    {
        _hLib = LoadLibraryEx(fileName, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_IGNORE_CODE_AUTHZ_LEVEL);

        if (_hLib == 0)
        {
            Console.WriteLine("********* Failed to load {0}.\r\nSpecified file was either not found, or is not a valid PE file.********", fileName);
            return;
        }

        ScanHeaders();
    }

    private static unsafe void ScanHeaders()
    {
        byte* pDosHeader = (byte*) _hLib;
        Console.WriteLine("pDosHeader[0] = {0}", pDosHeader[0]); // <<---- this is where it throws 'AccessViolationException' 
    }

    // From winbase.h in the Win32 platform SDK.
    //
    const uint DONT_RESOLVE_DLL_REFERENCES = 0x00000001;
    const uint LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010;

    [DllImport("kernel32.dll"), SuppressUnmanagedCodeSecurity]
    static extern uint LoadLibraryEx(string fileName, uint notUsedMustBeZero, uint flags);
}

1 个答案:

答案 0 :(得分:3)

可能还有其他问题,但最重要的问题是:

private static uint _hLib;

HMODULE是指针大小的。你的演员byte*应该清楚这一点。但uint是32位宽,可能会发生。您需要将_hLib声明为指针大小。例如:

private static IntPtr _hLib;

或者

private static UIntPtr _hLib;

这可以解释为什么代码在64位进程内运行时会失败。

也就是说,如果要扫描DLL的标头,则不必使用LoadLibraryEx。简单地打开文件并阅读其内容。