C# x64 0xc0000374上的.NET 4.0字符*到字符串互操作崩溃

C# x64 0xc0000374上的.NET 4.0字符*到字符串互操作崩溃,c#,wpf,.net-4.0,pinvoke,32bit-64bit,C#,Wpf,.net 4.0,Pinvoke,32bit 64bit,我目前正在将我们公司的x86软件迁移到x64,遇到了一个障碍。当解决方案平台切换到x64时,从非托管dll返回char*的方法与0xc0000374崩溃,我想知道原因 C++本机代码: #include "stdafx.h" #include <windows.h> #include "windef.h" #define VERSION "3.3.12" extern "C" { __declspec(dllexport) char* WINAPI GetMyVersion()

我目前正在将我们公司的x86软件迁移到x64,遇到了一个障碍。当解决方案平台切换到x64时,从非托管dll返回
char*
的方法与0xc0000374崩溃,我想知道原因

C++本机代码:

#include "stdafx.h"
#include <windows.h>
#include "windef.h"
#define VERSION "3.3.12"

extern "C"
{
  __declspec(dllexport) char* WINAPI GetMyVersion()
  {
    return (char*)VERSION;
  }
}
GetMyVersionString()
仅在x86平台上工作,在x64平台上崩溃。但是,我能够获取
IntPtr
,并使用
Marshal
类将其转换为x86和x64上的托管
字符串,如下所示:

using System.Runtime.InteropServices;
using System.Windows;
using InteropTest.Adapter;

namespace InteropTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            var ptr = MyAdapter.GetMyVersionPtr();
            var convertedString = Marshal.PtrToStringAnsi(ptr);

            // This crashes in x64 build
            var directString = MyAdapter.GetMyVersionString();

            VersionTextBlock.Text = convertedString;
        }
    }
}
编辑3:


非托管C++代码是我们的解决方案中的一个项目,X64/x86配置是建立起来的,类似于上面链接的示例项目。

嗯,您的版本不是“字符串”,它确实是指向原始内存的指针。如果您告诉.NET framework该指针是字符串,它将尝试取消分配该指针

因此,您有两种选择:

  • 像您一样使用IntPtr,这很好
  • 使用COM分配器分配.NET可以理解的一个真正的字符串,因此,在您的情况下,您的C++代码可以被替换为:


注意:您也可以使用BSTR。

您得到的异常是什么?您没有说明是否有不同版本的非托管dll(x86/x64)@PatrickHofman我在帖子中添加了关于崩溃的信息。@spender非托管代码是解决方案中的一个项目,并且设置了x86/x64配置。因此CLR假设这是一个返回字符串的DllImported方法,需要使用CoTaskMemFree释放memeory,并为我这样做:但是我们的x86平台上仍然存在不正确的代码。@ChenHuang-不是因为它没有崩溃,它才“工作”。许多臭虫永远活在人们的视线之外。
using System.Runtime.InteropServices;
using System.Windows;
using InteropTest.Adapter;

namespace InteropTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            var ptr = MyAdapter.GetMyVersionPtr();
            var convertedString = Marshal.PtrToStringAnsi(ptr);

            // This crashes in x64 build
            var directString = MyAdapter.GetMyVersionString();

            VersionTextBlock.Text = convertedString;
        }
    }
}
    ntdll.dll!00007ffc0fdc4cfa()    Unknown
    ntdll.dll!00007ffc0fdcc806()    Unknown
    ntdll.dll!00007ffc0fdccad1()    Unknown
    ntdll.dll!00007ffc0fd69a55()    Unknown
    ntdll.dll!00007ffc0fd77347()    Unknown
    mscorlib.ni.dll!00007ffbd566759e()  Unknown
    [Managed to Native Transition]  
>   InteropTest.exe!InteropTest.MainWindow.OnLoaded(object sender, System.Windows.RoutedEventArgs e) Line 23    C#
    PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised)    Unknown
__declspec(dllexport) char* WINAPI GetMyVersion() {
      char* p = (char*)CoTaskMemAlloc(7);
      CopyMemory(p, VERSION, 7);
      return p;
}