c_str()
returns a non-modifiable pointer. It must not be written to. Casting away const-ness and writing to the controlled sequence results in undefined behavior.
Instead, simply query for a pointer into the resource section, together with the string length, and construct a new std::wstring
object on this data:
std::wstring LoadStringW( unsigned int id )
{
const wchar_t* p = nullptr;
int len = ::LoadStringW( nullptr, id, reinterpret_cast<LPWSTR>( &p ), 0 );
if ( len > 0 )
{
return std::wstring{ p, static_cast<size_t>( len ) };
}
// Return empty string; optionally replace with throwing an exception.
return std::wstring{};
}
There are a few points worth noting:
- The implementation uses LoadString, passing
0
for nBufferMax. Doing so returns a pointer into the resource section; no additional memory allocation is performed:
nBufferMax:
If this parameter is 0, then lpBuffer receives a read-only pointer to the resource itself.
- String resources are counted strings, and can contain embedded
NUL
characters. This mandates the use of a std::string constructor taking an explicit length argument. return std::wstring(p);
would potentially truncate the returned string.
- Due to the layout of string resources, it is not generally possible to tell, if the string resource for any given ID is empty, or doesn't exist. The implementation in this answer follows suit, and returns an empty string if a string resource is empty, or does not exist.