1

I'm making a function that return a pointer to a wchar_t, but it returns nothing each time I use it.

Function:

wchar_t *Character::getCharHealth() {
    wchar_t charHealth[256];
    swprintf_s(charHealth, L"%d", this->getHealth());
    wprintf(L"%s\n", charHealth);
    wchar_t* cHealth = charHealth;
    return cHealth;
}

The getHealth() function:

int Character::getHealth() {
    return this->health;
}

Where it is used:

spriteFont->DrawString(spriteBatch.get(), warrior->getCharHealth(), DirectX::SimpleMath::Vector2(40, 0));

Is there anything wrong with my code?

4 Answers4

2

cHealth is a pointer to charHealth, which is local to the getCharHealth function. Once the function returns, the memory used by charHealth is deallocated, so cHealth is a wild pointer. One possible solution would be to allocate space for charHealth on the heap using new instead.

Jeff Ames
  • 1,424
  • 10
  • 18
1

The problem is that you're trying to return wchar_t charHealth[256];

However, this is a local variable and is destroyed at the end of the function. While you can take its address it means nothing once you exit the function so that's why you can't use the return.

If you want to return an array you make in a function, you need to explictely allocate it with new: wchar_t *charHealth = new wchar_t[256];

meneldal
  • 1,717
  • 1
  • 21
  • 30
  • There are also other problems in your code (such as allocating a huge string for storing only an integer and also using `wchar_t` in the first place which tends to be a bad idea) but I only answered the issue you raised – meneldal May 12 '15 at 03:33
1

You are returning a pointer to a array that's already out of scope, that's, wchar_t charHealth[256] belongs to getCharHealth() once it's done running it's undefined behaviour to access the charHealth array again.

What you could try is allocate a dynamic buffer for charHealth and return that instead:

wchar_t *Character::getCharHealth() {
    wchar_t* charHealth = new wchar_t[256];
    swprintf_s(charHealth, L"%d", this->getHealth());
    wprintf(L"%s\n", charHealth);
    return charHealth;
}

You then must remember to delete[] it when no longer needed:

wchar_t* cHealth = warrior->getCharHealth();
spriteFont->DrawString(spriteBatch.get(), cHealth, DirectX::SimpleMath::Vector2(40, 0));
delete[] cHealth;

That's very error prone you might forget to delete[]. Instead you could use std::unique_ptr<wchar_t[]> which automatically deletes the pointer on destruction. That's a technique called RAII if you are no familiar with.

But really, you probably should use a std::wstring with std::to_wstring to convert the number from int to std::wstring, since such a object contains proper string storage optimizations and takes care of any allocation that might be necessary.

std::wstring Character::getCharHealth() {
    std::wstring charHealth = std::to_wstring(this->getHealth());
    wprintf(L"%s\n", charHealth.c_str());
    return charHealth;
}

To access the raw const wchar_t* from a std::wstring you should use the .c_str() method, like so:

spriteFont->DrawString(spriteBatch.get(), warrior->getCharHealth().c_str(), DirectX::SimpleMath::Vector2(40, 0));
Denilson Amorim
  • 9,642
  • 6
  • 27
  • 31
0

This is caused by return a local allocated array on the stack. After your function Character::getCharHealth return, the memory space will be overwrite by your program.

Your gcc or clang compiler should output warning message for this, double check these msg could save much of your time.

For clang, the warning is controled by flag -Wreturn-stack-address, which is defaultly turned on. For gcc, the warning is controled by flag -Wreturn-local-addr, which is also turned on defaultly.

Kun Ling
  • 2,211
  • 14
  • 22