如果从函数返回 const char*,则 LPCWSTR 损坏
Posted
技术标签:
【中文标题】如果从函数返回 const char*,则 LPCWSTR 损坏【英文标题】:LPCWSTR corruption if const char* returned from a function 【发布时间】:2019-07-20 21:22:24 【问题描述】:我遇到了一个非常奇怪的问题。
我希望在 Windows 上使用 MessageBox(扩展为 MessageBoxW)输出一个简单的字符串。
以下是我正在使用的方法:
void MainWindow::ShowMessageBox( const std::wstring& title,const std::wstring& message ) const
MessageBox( hWnd,message.c_str(),title.c_str(),MB_OK );
std::wstring ConversionHelpers::s2ws(const std::string& s)
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
void DebugHelpers::MsgBox(MainWindow& window, const char* title, const char* message)
std::string t(title);
std::string m(message);
window.ShowMessageBox(ConversionHelpers::s2ws(t), ConversionHelpers::s2ws(m));
这行得通:
MsgBox(wnd, "Test", std::string("Hello").c_str());
这不起作用:
const char* get_hello()
return std::string("Hello").c_str();
MsgBox(wnd, "Test", get_hello());
“不起作用”是指我得到了大量奇怪的字符。
我知道在此示例中不需要转换,但在我的实现中,这是必要的。但这并不能回答关于奇怪的问题。
我对两者都做同样的事情,但是使用一种方法来返回值,而不是直接访问它。
【问题讨论】:
字符串字面量转换为wstring,尝试在它前面放一个L,L"test"std::wstring
中的w
代表wchar_t
和宽字符。它们不同于使用char
的窄字符。
@chris:你是对的。
犯了一个小错误,更新问题
@RickyFisher 调试那些转换函数。这是完成大部分工作的地方。
【参考方案1】:
get_hello()
创建的 std::string
在退出时超出范围时会被释放,而返回的 char*
在您甚至可以使用之前就指向无效内存。
最好让get_hello()
返回std::string
,然后调用者可以在返回的std::string
上调用c_str()
添加需要:
std::string get_hello()
return std::string("Hello");
MsgBox(wnd, "Test", get_hello().c_str());
【讨论】:
【参考方案2】:std::string::c_str
返回的指针指向std::string
对象拥有的内存。当关联的std::string
对象被销毁时,该内存被释放。任何进一步尝试访问它都会导致未定义的行为。
匿名临时对象(例如使用std::string("Hello").c_str()
创建的std::string
对象)一直存在到创建它们的完整表达式的末尾。这实质上意味着它们在下一个分号处超出范围。
当您调用MsgBox(wnd, "Test", std::string("Hello").c_str());
时,临时的std::string
会一直存在,直到MsgBox
函数调用结束。当它超出范围时,MsgBox
已使用它,并且没有其他尝试访问由c_str
返回的指针所指向的内存。一切都很好。
在第二种情况下,您再次创建一个临时的 std::string
对象。这次它只存在到get_hello
中的return
语句结束。当控制返回到调用函数时,在get_hello
中创建的临时std::string
已经消失,您返回的指针悬空,指向无效内存。
【讨论】:
我应该使用 memcpy 或类似的东西来获取 const char* 的副本,而不是使用由 c_str() 指向的现已删除的值生成的副本吗? 您应该只返回std::string
对象并让它管理内存,正如@RemyLebeau 在他们的回答中显示的那样。您可以分配自己的内存,但这样做会更复杂、更容易出错,而且效率可能更低。以上是关于如果从函数返回 const char*,则 LPCWSTR 损坏的主要内容,如果未能解决你的问题,请参考以下文章
可以/为啥在返回类型中使用 char * 而不是 const char * 会导致崩溃?
VS2017中遇到不存在从string到const char*的转换函数的解决方法
模板类 char*,函数 const char* 的返回类型?