c++ - End of WCHAR* contains junk -
i'm working on small project have manage file i/o (this i'm quit new to). i'm using win32 api unicode character-set , therefore store file-data using wide-characters, , strings in program stored using std::wstring. part of function reads , returns strings:
//get string file , return //(nchars amount of characters read) wchar * resultbuffer = new wchar[nchars]; file.read(resultbuffer, nchars); std::wstring result = resultbuffer; delete[] resultbuffer; return result;
however noticed result contains bunch of garbage characters @ end (the entire string read correctly file, garbage characters appended @ end). upon further inspection noticed these characters appear after resultbuffer gets allocated. wouldn't problem if over-written appear appended, , copied result aswell (meaning result gets more elements intended), leads lot of problems using them later. managed fix problem adding it:
//get string file , return wchar * resultbuffer = new wchar[nchars]; file.read(resultbuffer, nchars); std::wstring temp = resultbuffer; std::wstring result; (int = 0; < nchars; i++) { //note: shouldn't necessary result.push_back(temp.at(i)); } delete[] resultbuffer; return result;
this fixes problem feel though shouldn't needed. suspected might have how read function (std::wifstream::read()) works, looked @ documentation , found no clue. don't have experience using unicode , wide chars might obvious i'm missing, i'm out clue. got ideas? how resultbuffer looks after read() has been called (stackoverflow prints them kind of middle-eastern characters, appear asian ones in visual studio).
- resultbuffer l"\\.\display1﷽﷽☐☐ﰾ헏✀耀☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐☐" wchar_t *
edit: remy lebeau , mksteve providing great explanations aswell answers! working code:
//get string file , return std::wstring result; result.resize(nchars); file.read(&result[0], nchars); return result;
you calling std::wstring
constructor expects null-terminated wchar_t*
string, not null-terminating buffer. allocate +1 more wchar , set 0:
wchar * resultbuffer = new wchar[nchars+1]; file.read(resultbuffer, nchars); resultbuffer[nchars] = l'\0'; std::wstring result = resultbuffer; delete[] resultbuffer; return result;
alternatively, if specify buffer length when constructing std::wstring
, don't need null terminator:
wchar * resultbuffer = new wchar[nchars]; file.read(resultbuffer, nchars); std::wstring result(resultbuffer, nchars); delete[] resultbuffer; return result;
either way, should use std::vector
manage memory buffer instead of using new[]
/delete[]
manually:
std::vector<wchar> resultbuffer(nchars+1); file.read(&resultbuffer[0], nchars); resultbuffer[nchars] = l'\0'; return std::wstring(resultbuffer.data());
std::vector<wchar> resultbuffer(nchars); file.read(&resultbuffer[0], nchars); return std::wstring(resultbuffer.data(), nchars);
or, can rid of buffer altogether , read directly std::wstring
itself:
std::wstring result; result.resize(nchars); file.read(&result[0], nchars); // or result.data() in c++17 return result;
Comments
Post a Comment