从c#调用本机c ++的Stackoverflow

时间:2015-01-29 13:59:29

标签: c# c++-cli

我试图从C#项目调用本机C ++代码。为此,我按照this post中的步骤进行了操作。

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

//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.
    };
}

数组声明导致stackoverflow异常。

早些时候,当我只运行本机C ++代码时,我通过增加“堆栈保留大小”来增加堆栈大小。来自项目属性。

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

1 个答案:

答案 0 :(得分:5)

  int arr[640 * 480];

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

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

在C ++ / CLI程序中最好是array<int>^,它是存储在GC堆上的托管数组,就像C#数组一样。您使用pin_ptr&lt;&gt;允许本机代码在阵列上聚会。

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

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

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