如何安全地将字符串引用从c#传递到c++;? 我用C++ DLL项目开发了一个C语言的DLL项目。 让我们说C++ DLL登录到某个网站,并在Web服务器上做一些查询。 和C++ +DLL必须返回网站的HTML代码。 同时,C++ DLL必须保存网站上的Cookie数据。 StringBuilder将对象传递给C++函数。 我已经知道如何使用在C语言中使用的HTTPWebRebug和HTTPWebRead来从Web站点获取HTML代码,但不幸的是,我必须在C++ DLL项目中执行。

如何安全地将字符串引用从c#传递到c++;? 我用C++ DLL项目开发了一个C语言的DLL项目。 让我们说C++ DLL登录到某个网站,并在Web服务器上做一些查询。 和C++ +DLL必须返回网站的HTML代码。 同时,C++ DLL必须保存网站上的Cookie数据。 StringBuilder将对象传递给C++函数。 我已经知道如何使用在C语言中使用的HTTPWebRebug和HTTPWebRead来从Web站点获取HTML代码,但不幸的是,我必须在C++ DLL项目中执行。,c#,c++,string,reference,C#,C++,String,Reference,所以请记住,我不需要任何C代码 我试过了 从C#传递StringBuilder并将其作为LPTSTR 它工作正常,但结果中缺少一些字符串 我找不出原因 不管怎样,这是我的代码 C++ 它很好用 使用StringBuilder作为cookie,我可以继续创建网站的下一个url (我在C++项目中使用LIcURL) 但问题是我有大约100个ID 当它运行大约3~40时,返回heap error Debug Assertion Failed! Program: ~~~~mics\dbgheap.c L

所以请记住,我不需要任何C代码

我试过了

从C#传递StringBuilder并将其作为LPTSTR

它工作正常,但结果中缺少一些字符串

我找不出原因

不管怎样,这是我的代码

C++

它很好用

使用StringBuilder作为cookie,我可以继续创建网站的下一个url

(我在C++项目中使用LIcURL) 但问题是我有大约100个ID

当它运行大约3~40时,返回heap error

Debug Assertion Failed!
Program: ~~~~mics\dbgheap.c
Line: 1424

Expression: _pFirstBlock == pHead

我无法单击中止、重试或忽略按钮

看起来C#应用程序挂起了

我读了很多关于dbgheap调试断言失败的文章

主要类似于从另一堆释放内存对象

我是C++新手,

我在网上读了埃德森的问题

但是错误并不总是在特定的时间出现

所以我猜,当.NET运行垃圾收集器时会发生这种情况

net垃圾收集器试图释放由C++ DLL创建的内存,并且我得到堆错误。
Debug Assertion Failed!
Program: ~~~~mics\dbgheap.c
Line: 1424

Expression: _pFirstBlock == pHead
我说得对吗

我想他和我的问题是一样的

< >避免堆错误的最佳方法是什么?从C++ dll返回正确的字符串到c*dll?

p/S:堆错误只有在我运行调试模式时才会发生。我在运行发布模式时没有收到错误

编辑

根据WhozCraig的回答,我改变了我的代码如下

//return ::SysAllocString(CComBSTR(html.c_str()).Detach());
CComBSTR res(html.c_str());
return res.Detach();

<>但是没有运气,我仍然有堆错误。

你的问题是标题要求把字符串引用从C到C传递到C++,但是在后面的文本中,你问如何从C++返回字符串C。而且,你告诉你C++是新的。考虑到这一点,我将告诉你上次我是如何进行这种互动的。我只是让C++端分配和释放所有内存,只传递给C++,代码< ItpTrt>代码> PtrToStringAnsi。(P)< /COD> ED。在我的例子中,C++中存储RESERITY线程局部并在每个函数调用中释放它们是足够的,但是你可以制作一个C++函数,释放任何给定的REF。不是很聪明,也不一定是最有效的方法,但它是有效的

Debug Assertion Failed!
Program: ~~~~mics\dbgheap.c
Line: 1424

Expression: _pFirstBlock == pHead
upd: 它做的就是它做的。一些快速的谷歌搜索结果。我认为它很好,所以你可以参考它而不是我的建议。如果指针不能自行释放(例如,像旧的Delphi/C++Builder样式的字符串),并且您更喜欢在托管端而不是在本机端被打扰,那么传递raw
IntPtr
s是好的

作为一个例子,做Delphi交互的代码(对C++ Builder也是好的):


看起来你的问题很简单。您正在创建一个最多可容纳1024个字符的
StringBuilder
。如果C++函数返回的次数超过了,那么应用程序将崩溃(迟早)。p> 因此,要解决您的问题,请将
StringBuilder
的大小增加到可能的最大输出长度。更多详细信息:哪些引用:

唯一的 需要注意的是,StringBuilder必须 分配足够的空间给 返回值,否则文本将 溢出,导致出现异常 由P/Invoke抛出


< >在动态字符串长度中,在C++函数中使用BSTR参数实际上可能更好。在C++中,可以使用<代码> [ MsHalalas(unMaundType,ANSIBSTR),OUT ] REF字符串…< /COD> >和<代码> BSTR*<代码> > C++,

相关,这是:<代码>返回::SysAllocString(CComBSTR(HTML(CyString)))代码>是内存泄漏。您正在分离CComBSTR(这意味着它现在是一个原始的BSTR),然后返回该CComBSTR的SysAllocString,永远泄漏分离的BSTR。只要这样做:
ccombstrres(html.c_str());返回res.Detach()有没有理由不把C++放入C++ + CLR模式中,并传递到Studio?Stand,并在C++级别处理这个问题?这使得使用things更容易。你使用的互操作被设计成与“遗留纯C”集成界面集成——如果你拥有C++代码,只要打开集成。你的StastFf()函数调用会在有太多cookies时破坏堆。Cookies参数除了使程序崩溃之外没有任何用处。移除它。并且注意它在C++代码中什么也不做,所以也只需要删除Safftff()调用。在尝试调用它之前,彻底地测试C++代码。@ WoZoCrigg我将尝试更改我的代码。@ TimToM是C++或CLR,可以用JavaDeCupe这样的反编译器来反编译,等等?如果是这样,我就不能使用它。当StringBuilder大小太小时,它会抛出缓冲区溢出异常。不是堆错误。因此,与StringBuilder无关。事实上,cookie(StringBuilder)的大小只能容纳20个字符。“事实上,cookie(StringBuilder)的大小只能容纳20个字符。”-你是什么意思?如果你说的是“100个ID”,我认为20个字符不足以容纳它们。@JoshuaSon同样,我怀疑你会得到BufferOverFlowException。sprintf()当然不会在写入太小的缓冲区时抛出异常,它会失败得很惨。请仔细检查。如果你看到void SomeThing函数,我总是用new关键字重新创建StringBuilder。@JoshuaSon可能是这样,但我仍然看不到这个缓冲区有多大。你能给我看一篇Marshal的文章吗
    // function Get_TI_TC(AuraFileName:PAnsiChar; var TI,TC:PAnsiChar):Boolean; stdcall; external 'AuraToIec104.dll' name 'Get_TI_TC';
    [DllImport("AuraToIec104")]
    [return: MarshalAs(UnmanagedType.I1)]
    private static extern bool Get_TI_TC(string AuraFileName, out IntPtr TI, out IntPtr TC);
    public static bool Get_TI_TC(string AuraFileName, out string TI, out string TC)
    {
        IntPtr pTI, pTC;
        bool result = Get_TI_TC(AuraFileName, out pTI, out pTC);
        TI = Marshal.PtrToStringAnsi(pTI);
        TC = Marshal.PtrToStringAnsi(pTC);
        return result;
    }