-1

I just started using GDI+ and there will be quite a few conversions.

The text I draw appears for a split second as a bunch of random symbols. I traced the problem down to the conversions.

Code updated at bottom

const wchar_t* convert::stringToWideChar(string String) {

  wstring wideString;

  for(int i = 0; i < String.length(); i++)
      wideString += wchar_t( String[i] );

  return wideString.c_str();

}

Used as:

testing = "Two Two";
const wchar_t* buf = convert::stringToWideChar(testing);
path.AddString(buf, wcslen(buf), &gFontFamily, FontStyleBold, 72, ptOrg, &strFormat);

picture

The background is how the text is initially drawn. "Level 0" is what should be initially drawn. (In the screenshot the initial text is faded as should.)

Any ideas to do the conversion faster? (The strangest thing is it only happens with random specific strings, i.e. "Two" works, "Two Two", doesn't, "Two Too", does.

Updated

wstring convert::stringToWideChar(string String) {
wstring wideString;

for(int i = 0; i < String.length(); i++)
    wideString += wchar_t(String[i] );

return wideString;
}

Used as:

const wchar_t* buf = convert::stringToWideChar("leveljjj").c_str();
Evan Carslake
  • 2,267
  • 15
  • 38
  • 56
  • 9
    [undefined behaviour](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – chris May 21 '14 at 20:02
  • 4
    To clarify, `stringToWideChar` returns a pointer to a buffer owned by the local variable `wideString`, which is destructed when the method exits. – Joachim Isaksson May 21 '14 at 20:05

3 Answers3

1

Re: your updated code;

There is a difference in lifetime between an automatic variable and a temporary.

An automatic variable is declared in the function and will persist until the end of the scope.

A temporary will only persist until the end of the expression of which it is a part.

An example;

testing = "Two Two";
const wchar_t* buf = convert::stringToWideChar("leveljjj").c_str();
path.AddString(buf, wcslen(buf), &gFontFamily, FontStyleBold, 72, ptOrg, &strFormat);

In this case the string returned from stringToWideChar is a temporary. It only persists until the expression of which it is a part is complete, that is until the assignment line is finished. It will be destroyed before the path.AddString line.

If you on the other hand did this;

testing = "Two Two";
std::wstring value = convert::stringToWideChar("leveljjj");
const wchar_t* buf = value.c_str();
path.AddString(buf, wcslen(buf), &gFontFamily, FontStyleBold, 72, ptOrg, &strFormat);

...value is an automatic variable, which persists until the end of the scope. That means, it's safe to use the buffer returned since the variable is still valid for the AddString line.

Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
1

In your updated code your c_str() call will return a pointer into to a temporary object (rvalue) which is destroyed at the semicolon.

You'd need something like this:

void stringToWideChar(string String, char* destination) {
    wstring wideString;

    for(int i = 0; i < String.length(); i++)
        wideString += wchar_t(String[i] );

    memcpy(destination, wideString.c_str(), strlen(wideString.c_str));
}

Make sure to preallocate your buf, fill it with 0 (to get 0 termination), etc.

0

If you change your conversion function to return a wstring, that will remove the dangling reference in your code.

  • Just did, again, some reason it is still doing the exact same thing. Updated code in first post. Tested the function outside of my convert:: class. It does the exact same thing. The initial draw (very first) draws weird characters. All drawing after that, it displays just fine... – Evan Carslake May 21 '14 at 20:49