如果从函数返回 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* 的返回类型?

实现 reverse(const char *s1 , char *s2)

如何从 char* 函数返回指针

const