简体   繁体   中英

Returning a wchar_t in C++

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?

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.

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];

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));

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM