-1

I am converting a std::string to a char[] in a c++ dll application to pass through to a C# application.

in my Header i have:

char m_Text[1000];

in my cpp function:

void createLogEntry(std::string logMessage)
{
    logMessage = "testing testing";
//  logMessage = "testing testing 12121221.121212  ,1  12. .121212. .2 2 21";

    log_mutex.lock();
    snprintf ( m_Text, 100, logMessage.c_str() );

    log_mutex.unlock();

}

When I run the shorter string "testing testing", everything is fine. When I run with the other, commented out string, the application crashes. Why is this? And what can I do about it? I have tried using strcpy(m_Text, logMessage.c_str());, I have tried a larger array, and i see the same thing.

anti
  • 3,011
  • 7
  • 36
  • 86
  • 3
    Why are you using `snprintf` if you're not using a format string? – tkausl Sep 28 '18 at 18:09
  • What is `m_Text`? How big is it? – NathanOliver Sep 28 '18 at 18:10
  • I switched to `snprintf ` after reading that `strncpy()` does not always null terminate strings. Is that wrong? m_Text is `char m_Text[1000];`, as above. – anti Sep 28 '18 at 18:12
  • @anti Can you provide a [mcve]? – NathanOliver Sep 28 '18 at 18:14
  • 2
    Note that `logMessage.c_str()` gives you back a pointer to a `char[]` that you could pass to your C# application. You might not need all this wheel-spinning. – Pete Becker Sep 28 '18 at 18:18
  • 1
    You should use snprintf ( m_Text, 100, "%s", logMessage.c_str() ); to avoid the application crash. – tunglt Sep 28 '18 at 18:26
  • Unrelated: You may find [`std::lock_guard`](https://en.cppreference.com/w/cpp/thread/lock_guard) a worthwhile improvement to manually locking and unlocking a mutex. For example, it provides a satisfactory answer to the question, "What if an exception is thrown inside the protected region?" – user4581301 Sep 28 '18 at 18:30
  • 1
    Never. Ever. Use input data as a format string. Ever. It would be rather difficult to tell why your program crashes with this specific string without having a [mcve], but if you use `snprintf` the way you do, your program **will** crash sooner or later. – n. m. could be an AI Sep 28 '18 at 18:31

2 Answers2

1

I believe you have to use the format string as;

snprintf ( m_Text, 100, "%s", logMessage.c_str() );

more info can be found at

http://www.cplusplus.com/reference/cstdio/snprintf/

i have tried your way ;

snprintf ( m_Text, 100,logMessage.c_str() );

if the logmessage contains a format string as such as %s it treats it as a format string and starts looking for the fourth argument of snprintf to place where the %s. since this is not provided, it causes a crash.

enter image description here

Yucel_K
  • 688
  • 9
  • 17
0

When it is not guaranteed that logMessage.c_str() doesn't contain any % control character this can produce undefined behavior which can lead to a crash when it is for example expecting a pointer to char * from %s.

snprintf used the way how you do it interprets logMessage.c_str() as the format string!

How ever, use strcpy but before set m_Text to 0x00 with memset or std::memset.

For this you have to know the length/size if m_Text.

Using snprintf( m_Text, 100, "%s", logMessage.c_str() ) would be also safe - supposing m_Text is big enough to hold 100 characters.

Try to avoid constant size parameters - in this case 100. Once you change m_Text to a smaller size the program can also crash and you waste time to find the bug. sizeof(m_Text)-1 is much more safer - as long m_Text is NOT a pointer! Then sizeof would return the size of a pointer instead of the size of the array.

So, when you want to use snprintf this would be the best way:

snprintf( m_Text, sizeof(m_Text) - 1, "%s", logMessage.c_str() )

Peter VARGA
  • 4,780
  • 3
  • 39
  • 75