使用C#调用C++;dll,有时内存冲突 我有C++代码< /p>的定义 #define TEST_DLL_API extern "C" __declspec(dllexport) TEST_DLL_API void __cdecl create(const char* sString, const char* sNext, int level, char* response ) ; TEST_DLL_API void __cdecl result(const char* sString, char* response) ;
在我的C#代码中的前几次调用中,它工作得很好,但它第五次导致内存冲突使用C#调用C++;dll,有时内存冲突 我有C++代码< /p>的定义 #define TEST_DLL_API extern "C" __declspec(dllexport) TEST_DLL_API void __cdecl create(const char* sString, const char* sNext, int level, char* response ) ; TEST_DLL_API void __cdecl result(const char* sString, char* response) ;,c#,C#,在我的C#代码中的前几次调用中,它工作得很好,但它第五次导致内存冲突 [DllImport("TEST_DLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)] public static extern void create(string sString, string sNext, int level, StringBuilder response)
[DllImport("TEST_DLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)]
public static extern void create(string sString, string sNext, int level, StringBuilder response);
[DllImport("TEST_DLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)]
public static extern void result(string sString, StringBuilder response);
<>我想这是不是要释放栈内存,但我不知道如何解决它。
首先,忘记C,然后想想如何从另一个C/C++函数调用C++函数。去掉导出内容后,
result()
函数将声明为:
void result( const char* sString, char* response );
那么该函数的实现呢?假设它只是将输入sString
复制到输出响应
字符串。可能代码如下所示:
void result( const char* sString, char* response ) {
strcpy( response, sString );
}
#define elementsof( array ) ( sizeof(array) / sizeof((array)[0]) )
// ...
char buffer[10];
result( "This is my input string", buffer, elementsof(buffer) );
甜蜜而简单,对吗
好,现在让我们调用这个函数
char buffer[10];
result( "This is my input string", buffer );
你认为这里可能有问题吗<代码>缓冲区长度仅为10个字符,但输入字符串为24个字符,包括终止null
因此,result()
函数将把24个字符复制到10个字符的缓冲区中。哎呀
事实上,result()
函数如何知道响应
缓冲区中有多少可用空间?它没有办法知道这一点
要使函数在C/C++中可用,还必须传入最大缓冲区长度,然后result()
可以使用该长度限制它复制的内容的长度。它可以通过使用strcpy\u s()
而不是strcpy()
:
你可以这样称呼它:
void result( const char* sString, char* response ) {
strcpy( response, sString );
}
#define elementsof( array ) ( sizeof(array) / sizeof((array)[0]) )
// ...
char buffer[10];
result( "This is my input string", buffer, elementsof(buffer) );
即使输入字符串比输出缓冲区大,您也可以,因为只有足够的字符串会被复制到缓冲区中
现在,您还可以使用StringBuilder
从C#调用一个函数,因为您可以分配StringBuilder
并将其长度传入:
[DllImport(
"TEST_DLL.dll",
CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi,
SetLastError = true
)]
public static extern void result(
string sString,
StringBuilder response,
int cchResponse
);
StringBuilder buffer( 10 );
result( "This is my input string", buffer, buffer.Capacity );
与上面的C/C++示例一样,即使输入字符串大于缓冲区,函数result()
也只会复制缓冲区中可用的字符数
一句话:如果将StringBuilder
传递到C/C++函数中以接收该函数的输出,则必须预先分配该函数,并且C/C++函数必须提供一种告诉它最大长度的方法
(我写这篇文章时没有测试代码;这里可能会有错误,但您应该了解大概情况。)