关于从 C# 调用本机 C++ 的 Stackoverflow

Stackoverflow on calling native c++ from c#

我正在尝试从 C# 项目调用本机 C++ 代码。为此,我按照 this post.

中的步骤操作

但是当我在 C++ 文件中创建一个巨大的数组时,我得到了一个 Whosebug 异常。这是代码:

//CSharpTest.h

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CpTest.Class1 instance = new CpTest.Class1();
            Console.WriteLine(instance.DoSomething());
            Console.ReadKey();
        }
    }
}

和 c++ 文件

// CpTest.h

#pragma once

using namespace System;

namespace CpTest {

    public ref class Class1
    {
    public:
        int DoSomething(){
            int arr[640 * 480];
            return 123;
        }
        // TODO: Add your methods for this class here.
    };
}

数组声明导致 Whosebug 异常。

早些时候,当我 运行 只是本机 C++ 代码时,我通过增加项目属性中的 'Stack Reserve Size' 来增加堆栈大小。

但是对于这种情况,我不知道该怎么办。

  int arr[640 * 480];

此数组存储在 C 或 C++ 程序的堆栈中。相当于 C# 程序中的 stackalloc。它需要 640 x 480 x 4 = 1,228,800 字节的存储空间。这太多了,堆栈的默认大小是 1 兆字节。你溢出了堆栈,异常会告诉你。

这是本机代码中的一个缺陷,它不应该依赖如此大的分配来在 运行 时间进行平移,而应该使用免费存储。 C++ 程序中的运算符 new,C 程序中的运算符 malloc

最好是 array<int>^ 在 C++/CLI 程序中,这是一个存储在 GC 堆上的托管数组,就像 C# 数组一样。您将使用 pin_ptr<> 来允许本机代码参与数组。

从技术上讲,它在 C# 项目中是可以修复的,您必须为启动线程请求更大的堆栈,即操作系统创建并调用您的 Main() 方法的堆栈。当您以 x64 为目标时,您会自动获得一个,默认值为 4 兆字节。但如果您必须与现有本机代码互操作,那通常不是一个选项。您可以 运行 Editbin.exe 使用 /STACK 选项来修补 EXE 文件头并请求更大的堆栈。 C# 项目中的 post-build 事件可能如下所示:

  set path=%path%;$(DevEnvDir);$(DevEnvDir)..\..\vc\bin
  editbin.exe /STACK:2097152 "$(TargetPath)"

或 运行 来自您自己创建的线程的本机代码,使用允许您指定堆栈大小的 Thread constructors 之一。