我试图从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 ++代码时,我通过增加“堆栈保留大小”来增加堆栈大小。来自项目属性。
但对于这种情况,我不知道该怎么做。
答案 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之一。