I have the below code in c++/CLI and observing hang while converting the .net string to char * using StringToCoTaskMemAnsi
const char* CDICashInStringStore::CDIGetStringVal( void )
{
unsigned int identifier = (unsigned int)_id;
debug(" cashincdistores--routing call to .Net for CDI String %d", identifier);
NCR::APTRA::INDCDataAccess::IStringValue^ stringValueProvider = (NCR::APTRA::INDCDataAccess::IStringValue^)GetStringProvider()->GetProvider();
String^ strValue = stringValueProvider->GetStringValue(identifier);
debug(" cashincdistores-- going to call StringToCoTaskMemAnsi);
IntPtr iPtr = Marshal::StringToCoTaskMemAnsi(strValue);
debug(" cashincdistores-- StringToCoTaskMemAnsi called);
// use a local (retVal is not needed)
const char * ansiStr = strdup((const char *) iPtr.ToPointer());
Marshal::FreeCoTaskMem(iPtr);
debug(" cashincdistores--got results %d %s",identifier,ansiStr);
// The returned memory will be free() 'ed by the user
return ansiStr;
}
In our logging I can see "cashincdistores-- going to call StringToCoTaskMemAnsi" and suspecting there is a hang after calling the 'StringToCoTaskMemAnsi' method.
Does there is a chance of hang in 'StringToCoTaskMemAnsi' marshalling method. what could cause the hang ?
Why are you using COM in the first place? You don't need any COM in that code.
Disclaimer: You should probably not be returning a
const char *
someone else will have to free from your function. That's a very easy way to produce memory leaks or multiple free errors.
Ignoring the disclaimer above, you have a couple possibilities:
First way:
#include <msclr/marshal.h>
msclr::interop::marshal_context context;
const char* strValueAsCString = context.marshal_as<const char*>(strValue);
// Probably bad
const char* ansiStr = strdup(strValueAsCString);
The strValueAsCString
pointer will remain valid as long as context
is in scope.
Another way:
#include <string>
#include <msclr/marshal_cppstd.h>
std::string strValueAsStdString = msclr::interop::marshal_as<std::string>(strValue);
// Probably bad
const char* ansiStr = strdup(strValueAsStdString.c_str());
Here, the std::string
manages the lifetime of the string.
See Overview of Marshaling for reference.