You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确将char转换为wchar_t?异常弹窗乱码问题求助

问题分析与解决方法

乱码原因

  1. 指针悬空导致未定义行为:你在catch (const ExceptionHandling& e)块中,将wideWhat和wideType赋值为局部std::wstring对象的c_str(),当局部的wideString离开其作用域(对应if块结束)后,字符串对象被销毁,指针变成野指针,此时调用MessageBox访问这些指针会读取到垃圾数据,表现为乱码。
  2. 编码转换依赖系统代码页:mbstowcs_s默认使用当前系统的ANSI代码页进行转换,如果异常信息的多字节编码(比如UTF-8)与系统代码页不匹配,转换过程会失败,同样导致乱码。

修复与简化方案

1. 避免指针悬空,保留字符串对象到MessageBox调用后

不要保存c_str()的指针,而是直接持有std::wstring对象,确保在调用MessageBox时对象仍然有效。

2. 使用更可靠的编码转换(针对UTF-8或ASCII英文)

如果异常信息是UTF-8编码的英文,推荐使用MultiByteToWideChar并指定CP_UTF8代码页,避免依赖系统默认编码;如果是ASCII英文,两种方式都可以,但MultiByteToWideChar更灵活。

3. 封装转换工具函数,消除重复代码

把多字节转宽字符串的逻辑封装成函数,避免在多个catch块中重复写相同代码。

简化后的完整代码

#include <windows.h>
#include <string>
#include <stdexcept>

// 多字节字符串转宽字符串工具函数(假设输入为UTF-8编码)
std::wstring utf8ToWide(const char* mbStr) {
    if (!mbStr) return L"";

    int wideSize = MultiByteToWideChar(CP_UTF8, 0, mbStr, -1, nullptr, 0);
    if (wideSize == 0) return L"";

    std::wstring wideStr(wideSize, L'\0');
    MultiByteToWideChar(CP_UTF8, 0, mbStr, -1, &wideStr[0], wideSize);
    return wideStr;
}

// 如果你的ExceptionHandling类的what()/GetType()是ASCII编码,也可以用这个版本(依赖系统代码页)
// std::wstring mbToWide(const char* mbStr) {
//     if (!mbStr) return L"";
//
//     size_t size;
//     if (mbstowcs_s(&size, nullptr, 0, mbStr, 0) != 0) return L"";
//
//     std::wstring wideStr(size, L'\0');
//     mbstowcs_s(nullptr, &wideStr[0], wideStr.size(), mbStr, size - 1);
//     return wideStr;
// }

// 异常捕获逻辑
void handleExceptions() {
    try {
        // 你的业务代码
        throw std::runtime_error("Runtime error occurred");
    }
    catch (const ExceptionHandling& e) {
        std::wstring wideWhat = utf8ToWide(e.what());
        std::wstring wideType = utf8ToWide(e.GetType());

        MessageBox(nullptr, 
                   wideWhat.empty() ? L"Unknown error detail" : wideWhat.c_str(), 
                   wideType.empty() ? L"Custom Exception" : wideType.c_str(), 
                   MB_OK | MB_ICONEXCLAMATION);
    }
    catch (const std::exception& e) {
        std::wstring wideWhat = utf8ToWide(e.what());
        MessageBox(nullptr, 
                   wideWhat.empty() ? L"Unknown error detail" : wideWhat.c_str(), 
                   L"Standard Exception", 
                   MB_OK | MB_ICONEXCLAMATION);
    }
    catch (...) {
        MessageBox(nullptr, L"No details available", L"Unknown Exception", MB_OK | MB_ICONEXCLAMATION);
    }
}

关键说明

  • 工具函数utf8ToWide明确指定UTF-8编码转换,适合大多数现代程序的字符串编码场景,确保英文内容转换准确。
  • 所有宽字符串对象在MessageBox调用前都保持有效,彻底避免指针悬空问题。
  • 代码结构更简洁,消除了重复的转换逻辑,易于维护。

内容的提问来源于stack exchange,提问作者descreetOP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 15:19:56