2

I'm writing code and a good portion of it requires returning wchar arrays. Returning wstrings aren't really an option (although I can use them) and I know I can pass a pointer as an argument and populate that, but I'm looking specifically to return a pointer to this array of wide chars. The first few iterations, I found that I would return the arrays alright, but by the time they are processed and printed, the memory would be overwritten and I would be left with gibberish. To fix this, I started using wcsdup, which fixed everything, but I'm struggling to grasp exactly what is happening, and thus, when it should be called so that it works and I leak no memory. As it is, I pretty much use wcsdup every time I return a string and every time a string is returned, which I know leaks memory. Here is what I'm doing. Where and why should I use wcsdup, or is there a better solution than wcsdup altogether?

wchar_t *intToWChar(int toConvert, int base)
{
    wchar_t converted[12];
    /* Conversion happens... */
    return converted;
}

wchar_t *intToHexWChar(int toConvert)
{
    /* Largest int is 8 hex digits, plus "0x", plus /0 is 11 characters. */
    wchar_t converted[11];

    /* Prefix with "0x" for hex string. */
    converted[0] = L'0';
    converted[1] = L'x';

    /* Populate the rest of converted with the number in hex. */
    wchar_t *hexString = intToWChar(toConvert, 16);
    wcscpy((converted + 2), hexString);

    return converted;
}

int main()
{
    wchar_t *hexConversion = intToHexWChar(12345);
    /* Other code. */

    /* Without wcsdup calls, this spits out gibberish. */
    wcout << "12345 in Hex is " << hexConversion << endl;
}
TMenninger
  • 33
  • 1
  • 5
  • `intToWChar` and `intToHexWChar` both return a pointer to a variable that will be out of scope after the function is complete. Don't do this. – crashmstr Aug 28 '15 at 12:56
  • Don't you need [wcout](http://stackoverflow.com/questions/2493785/how-i-can-print-the-wchar-t-values-to-console) here? – crashmstr Aug 28 '15 at 12:59
  • And why can't you just return a std::wstring instead of a raw pointer? – paulm Aug 28 '15 at 13:21
  • I do need wcout, but that's less important. The reason I haven't been using wstring is because this needs to fit into others' code. But now that I look at it I guess it's possible to use them until the last step and then extract a wchar array from the string... – TMenninger Aug 28 '15 at 15:31
  • --and others' code works almost exclusively with wchar arrays for whatever reason. – TMenninger Aug 28 '15 at 15:33

2 Answers2

0

Since you tagged your question with 'C++' the answer is a resounding: no, you should not use wcsdup at all. Instead, for passing arrays of wchar_t values around, use std::vector<wchar_t>.

If needed, you can turn those into a wchar_t* by taking the address of the first element (since vectors are guaranteed to be stored in contiguous memory), e.g.

cout << "12345 in Hex is " << &hexConversion[0] << endl;
Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
0
wchar_t *intToWChar(int toConvert, int base)
{
    wchar_t converted[12];
    /* Conversion happens... */
    return converted;
}

This returns a pointer to a local variable.

wchar_t *hexString = intToWChar(toConvert, 16);

After this line, hexString will point to invalid memory and using it is undefined (may still have value or may be garbage!).

You do the same thing with the return from intToHexWChar.

Solutions:

  • use std::wstring
  • use std::vector<wchar_t>
  • pass in an array to the function for it to use
  • use smart pointers
  • use dynamic memory allocation (please don't!)

Note: you might also need to change to wcout instead of cout

crashmstr
  • 28,043
  • 9
  • 61
  • 79
  • Okay, now let me add a level of abstraction. Often times, these strings/char arrays are being stored in structs to be later retrieved with myStruct.GetString(). I realize I can't really keep a pointer to a char array in a struct and expect the memory to be untouched, but wouldn't a wstring make this a struct of variable size, and if so, isn't that bad? – TMenninger Aug 28 '15 at 15:45
  • The only problem would be if you were writing binary data and expected a fixed size record. I would hazard a guess that most real-world data in modern C++ is not fixed size, but contains `std::string` as well as standard container classes (which also have variable size). As your question stands, I think this is a good answer. But since you don't actually give us the "real" usage, I don't know that we can answer better. – crashmstr Aug 28 '15 at 16:08