0

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 ?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Sadhu
  • 57
  • 7
  • Have you stepped through this with the debugger, or have you only done printf debugging? What happens when you step through that line? – David Yaw Jun 29 '16 at 15:47
  • Thanks David for your reply. Hang is not happening while debugging and moreover hang is happening very rarely (1 out of 50 times) – Sadhu Jun 29 '16 at 15:59
  • Sure, this is possible. You could deadlock on the lock that protects the heap if you do anything unwise like catching SEH exceptions. Or basic heap corruption can get the allocator stuck in an endless loop. Nasty problems, no one-button-fixes-it answers. – Hans Passant Jun 29 '16 at 16:55
  • which is thread safe "StringToCoTaskMemAnsi" or "StringToHGlobalAnsi" ? – Sadhu Jul 01 '16 at 06:42

1 Answers1

1

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.

Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158