небезопасный код c # вызывает повреждение кучи на 64-битной платформе, если он не построен для платформы x86 - PullRequest
2 голосов
/ 11 августа 2010

У меня есть простая утилита, которая использует небезопасный код для получения информации о версии файла. Когда я скомпилировал это как смешанную платформу (vs2008 / .net 3.5) и развернул на 64-битной машине, я получил ошибку повреждения кучи. Если я перекомпилирую как x86 то все работает ....

Это было удивительно из-за моего понимания .NET Common Type System. Мой небезопасный код использует указатель на короткий и указатель на байт. Разве эти распространенные типы одинакового размера на любой платформе из-за CTS? что мне здесь не хватает

using System;
using System.Reflection;
using System.Runtime.InteropServices;


public class Win32Imports
{
    [DllImport("version.dll")]
    public static extern bool GetFileVersionInfo(string sFileName,
          int handle, int size, byte[] infoBuffer);

    [DllImport("version.dll")]
    public static extern int GetFileVersionInfoSize(string sFileName,
          out int handle);

    // The third parameter - "out string pValue" - is automatically
    // marshaled from ANSI to Unicode:
    [DllImport("version.dll")]
    unsafe public static extern bool VerQueryValue(byte[] pBlock,
          string pSubBlock, out string pValue, out uint len);

    // This VerQueryValue overload is marked with 'unsafe' because 
    // it uses a short*:
    [DllImport("version.dll")]
    unsafe public static extern bool VerQueryValue(byte[] pBlock,
          string pSubBlock, out short* pValue, out uint len);
}

public class FileInformation
{
    // Main is marked with 'unsafe' because it uses pointers:
    unsafe public static string GetVersionInformation(string path)
    {

        // Figure out how much version info there is:
        int handle = 0;
        int size =
              Win32Imports.GetFileVersionInfoSize(path,
              out handle);
        if (size == 0) return "";

        byte[] buffer = new byte[size];
        if (!Win32Imports.GetFileVersionInfo(path, handle, size, buffer)) return "";

        // Get the locale info from the version info:
        short* subBlock = null;
        uint len = 0;           
        if (!Win32Imports.VerQueryValue(buffer, @"\VarFileInfo\Translation", out subBlock, out len)) return "";


        // Get the ProductVersion value for this program:
        string spv = @"\StringFileInfo\" + subBlock[0].ToString("X4") + subBlock[1].ToString("X4") + @"\ProductVersion";
        byte* pVersion = null;
        string versionInfo;
        if (!Win32Imports.VerQueryValue(buffer, spv, out versionInfo, out len)) return "";
        return versionInfo;

    }
}

Спасибо Убийца всех зомби и ожидание зомби-апокалипсиса ....... -Джонатан

Ответы [ 2 ]

2 голосов
/ 11 августа 2010

Есть ли причина, по которой вы не могли использовать для этого класс FileVersionInfo managed ?Я подозреваю, что он работает как на 32-битной, так и на 64-битной платформах.

1 голос
/ 11 августа 2010

Возможно, поскольку указатели являются 64-битными в платформе, но вы используете небезопасные, это не преобразуется правильно? Также, пожалуйста, покажите, как выглядит ваш импорт p / invoke.

...