C# gcnew object and long running SQL query

0

I have a process to select and run a SQL query. Sometimes (most times it works fine) this results in a crash at the end of the original calling function. The process goes like this (all method calls in instantiated classes); (Note; just listing processes due to actual code being 1000s of lines. I will try to provide more detail if needed)

Method call to QueryPicker (params) (c#)
QueryPicker calls cs_query_picker (params) (c++, in a loaded dll, shared by other services at the time)
cs_query_picker declares 100s of variables then calls QueryPickerWrapper (params) (c#)
QueryPickerWrapper uses gcnew

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

QueryPickerWrapper then calls MyQueryPicker (Params) //made with gcnew
This finds the SQL query and runs it. It can take up to 1200ms (not horrifyingly long really)
MyQueryPicker then sets Params (with the query result) and returns true (that something set)
QueryPickerWrapper when true is returned, sets the pointer

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

QueryPickerWrapper then returns true
cs_query_picker returns a 1 when it gets a 1 from QueryPickerWrapper, else it moves to older code (1998 stuff, would use the 100s of declared variables) to set params. In all the crashes, QueryPickerWrapper always returns a 1.
QueryPicker receives the 1, finishes the method using the param that was passed back, then crashes.

I've never caught an exception with the crash (I have a try/catch around it) and with the windows event log, it says
Faulting modulename: clr.dll, version:4.0.30319.34209
Exception Code: 0xc00000fd
Fault offset: 0x001a149f

To the best of my research this is a stack overflow. However, I don't know how it would be happening. I fell since the issue is intermittent (some times also every hour, sometimes not for days) that it is a relation between when the garbage collector runs and how long the SQL calls takes before returning.

The question: How is this occurring and what can I do to fix it?

This is compiled and run in .NET4.0

c#
c++
c++-cli
asked on Stack Overflow Jun 19, 2017 by xgo • edited Jun 19, 2017 by xgo

1 Answer

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

I can't tell what's a typo here, and what might be a coding problem.

  • Params = gcnew string, followed by Params->Str. Neither System::String nor std::string have a member named Str. Is Params a struct, or something like that?
  • Params, param, and params. You've got three almost identically named variables. If they're all typos of each other, then I have no idea what params->Str = gcnew String(params); is supposed to do.

.

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

OK, this one I can answer. Your main problem is that you're allocating a new HGlobal in StringToHGlobalAnsi, and never releasing it (a memory leak). You could keep the pointer around and free it, but I prefer to use std::string as a temporary variable. Everyone knows how to deal with a std::string, so there's no new rules to learn.

#include <msclr/marshal_cppstd.h>

std::string temp = marshal_as<std::string>(source);
strcpy_s(destination, PARAM_LEN+1, temp->c_str());
answered on Stack Overflow Jun 20, 2017 by David Yaw

User contributions licensed under CC BY-SA 3.0