不安全的 C# 代码会导致 64 位平台上的堆损坏,除非为 x86 平台构建

发布于 2024-09-13 11:57:04 字数 2299 浏览 12 评论 0原文

我有一个简单的实用程序,它使用一些不安全的代码来获取文件版本信息。当我将其编译为混合平台(vs2008/.net 3.5)并部署到 64 位计算机时,我收到堆损坏错误。如果我重新编译为 x86,那么一切都会正常......

这很令人惊讶,因为我对 .NET 通用类型系统的理解。我的不安全代码使用一个指向短整型的指针和一个指向字节的指针。由于 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;

    }
}

谢谢 所有僵尸的杀手并等待僵尸启示录...... -乔纳森

I have a simple util that uses some unsafe code to get the file version information. when I compiled this as mixed platform (vs2008/.net 3.5) and deploy to 64 bit machine I get a heap corruption error. If I recompile as x86 then everything works....

This was suprising because of my understanding of the .NET Common Type System. My unsafe code uses a pointer to a short and a pointer to a byte. Arent these common types the same size on any platform becuase of the CTS? what am I missing here

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;

    }
}

Thanks
Killer of All zombies and waiting for the zombie Apocolypse.......
-Jonathan

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深爱成瘾 2024-09-20 11:57:04

您是否有任何原因无法使用 FileVersionInfo 这个的托管类?我怀疑它在 32 位和 64 位平台上都能正常工作。

Is there any reason you couldn't use the FileVersionInfo managed class for this? I suspect it works properly on both 32 bit and 64 bit platforms.

手心的海 2024-09-20 11:57:04

也许因为平台中的指针是 64 位的,但您使用的是不安全的,所以这没有正确转换?另请显示您的 p/invoke 导入是什么样子的。

Perhaps since pointers are 64-bit in the platform, but you are using unsafe, this isn't transformed correctly? Also please show what your p/invoke imports look like.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文