2017-06-19 109 views
0

我有一个选择和运行SQL查询的过程。有时(大部分时间工作正常),这会导致原始调用函数结束时崩溃。过程像这样(在实例化类中的所有方法调用); (注;刚上市过程中,由于实际的代码是行1000我会尽量提供更多的细节,如果需要)。C#gcnew对象和长时间运行的SQL查询

方法调用QueryPicker(PARAMS)(C#)
QueryPicker调用cs_query_picker(PARAMS)(C++,在加载的DLL,由其他服务在时间共享)
cs_query_picker声明的变量100S然后调用QueryPickerWrapper(PARAMS)(C#)
QueryPickerWrapper使用gcnew

string ^Params = gcnew string; 
if (param != nullptr) 
Params->Str = gcnew String (params); 

QueryPickerWrapper然后调用MyQueryPicker(PARAMS)//用gcnew
制作 这找到了SQL查询并运行它。它可能需要长达1200ms(不horrifyingly长真)
MyQueryPicker然后设置PARAMS(与查询结果),并返回true(的东西设置)时返回true
QueryPickerWrapper,设置指针

if(params != nullptr) 
strcpy_s(params, PARAM_LEN+1, (char*)(void*)Marshal::StringToHGlobalAnsi(Params->Str)); 

QueryPickerWrapper然后返回true
cs_query_picker从QueryPickerWrapper获得1时返回1,否则它将移到较旧的代码(1998年的东西,将使用100个声明的变量)来设置参数。在所有崩溃中,QueryPickerWrapper总是返回1.
QueryPicker接收到1,使用传回的参数完成该方法,然后崩溃。

我从来没有补时崩溃(我周围有一个try/catch)异常,并与Windows事件日志,它说:
断裂作用MODULENAME:clr.dll,版本:4.0.30319.34209
异常代码:0xc00000fd
错误偏移量:0x001a149f

对我的研究来说,这是一个堆栈溢出。但是,我不知道它将如何发生。由于问题是间歇性的(有些时候也是每小时,有时不是几天),所以这是垃圾收集器运行时间与SQL调用返回之前需要多长时间之间的关系。

问题: 这是怎么发生的?我能做些什么来解决它?

这是编译和.NET4.0

+0

你可能最好是标记C++ CLI而不是C++。无论如何,这看起来很狡猾'(char *)(void *)Marshal :: StringToHGlobalAnsi(Params-> Str)'。也许一个'IntPtr'可以转换为c风格的字符串,但我怀疑它。我想你可能会错过像'toString'方法调用的步骤。 – user4581301

+0

我很近。 [根据MSDN](https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.stringtohglobalansi(v = vs.110).aspx),你错过了一个'.ToPointer( )' – user4581301

回答

0
string ^Params = gcnew string; 
if (param != nullptr) 
    Params->Str = gcnew String (params); 

运行我不能告诉什么是一个错字这里,什么可能是一个编码问题。

  • Params = gcnew string,其次是Params->StrSystem::Stringstd::string都没有名为Str的成员。参数是一个结构,或类似的东西?
  • Params,paramparams。你有三个几乎同名的变量。如果他们都是对方的拼写错误,那么我不知道params->Str = gcnew String(params);应该做什么。

strcpy_s(params, PARAM_LEN+1, (char*)(void*)Marshal::StringToHGlobalAnsi(Params->Str)); 

好的,这个我可以回答。你的主要问题是你在StringToHGlobalAnsi中分配一个新的HGlobal,并且永远不会释放它(内存泄漏)。你可以保持指针并释放它,但我更喜欢使用std::string作为临时变量。每个人都知道如何处理std::string,所以没有新的规则可以学习。

#include <msclr/marshal_cppstd.h> 

std::string temp = marshal_as<std::string>(source); 
strcpy_s(destination, PARAM_LEN+1, temp->c_str()); 
+0

看着C++文件使用Marshel行后,我觉得你是正确的,在这里发生了一个内存问题。我已经重写了queryPicker不使用c + + dll和崩溃已经消失。谢谢。另外,抱歉我的sudo代码部分很难。 – xgo