C++实现char*转wchar_t*且无内存泄漏的可靠方案咨询
最优实现方案
方案1:返回std::wstring(最推荐)
优先用标准库容器管理内存,完全避免内存泄漏和野指针问题,天然支持任意长度的输入字符串,无需手动干预资源释放:
#include <string> #include <cstring> #include <stdlib.h> std::wstring ConvertToWString(const char* str) { if (str == nullptr) return L""; // 预计算转换需要的宽字符总数量(包含结束符) size_t requiredSize = 0; mbstowcs_s(&requiredSize, nullptr, 0, str, _TRUNCATE); if (requiredSize == 0) return L""; std::wstring wstr(requiredSize - 1, L'\0'); // requiredSize包含结束符,实际有效字符少1位 size_t convertedCnt = 0; mbstowcs_s(&convertedCnt, wstr.data(), requiredSize, str, _TRUNCATE); return wstr; }
调用时直接用std::wstring接收返回值即可,变量离开作用域后会自动释放内存。
注意:你原有的实现直接使用
strlen(str)+1作为宽字符缓冲区长度存在隐患,当输入是多字节编码(比如UTF-8)时,字节数不等于宽字符数,可能导致缓冲区不足出现截断,推荐先调用mbstowcs_s预计算所需的宽字符长度。
方案2:必须返回原生wchar_t*的场景
如果上层逻辑强依赖原生指针,有两种安全实现可选:
2.1 约定调用者手动释放
在函数注释中明确内存释放规则,要求调用者用完后主动执行delete[]释放内存:
/** * @brief 转换char*为wchar_t* * @note 调用者必须在使用完返回值后执行 delete[] 释放内存,否则会出现内存泄漏 */ wchar_t* ConvertToWString(const char* str) { if (str == nullptr) return nullptr; size_t requiredSize = 0; mbstowcs_s(&requiredSize, nullptr, 0, str, _TRUNCATE); if (requiredSize == 0) return nullptr; wchar_t* wstr = new wchar_t[requiredSize]; size_t convertedCnt = 0; mbstowcs_s(&convertedCnt, wstr, requiredSize, str, _TRUNCATE); return wstr; }
调用示例:
wchar_t* wstr = ConvertToWString("测试字符串"); // 业务逻辑使用wstr delete[] wstr; // 必须手动释放内存
2.2 返回智能指针(自动释放)
用std::unique_ptr<wchar_t[]>包装原生指针,离开作用域后自动释放内存,不需要手动管理:
#include <memory> std::unique_ptr<wchar_t[]> ConvertToWString(const char* str) { if (str == nullptr) return nullptr; size_t requiredSize = 0; mbstowcs_s(&requiredSize, nullptr, 0, str, _TRUNCATE); if (requiredSize == 0) return nullptr; auto wstr = std::make_unique<wchar_t[]>(requiredSize); size_t convertedCnt = 0; mbstowcs_s(&convertedCnt, wstr.get(), requiredSize, str, _TRUNCATE); return wstr; }
调用示例:
auto wstr = ConvertToWString("测试字符串"); // 调用wstr.get()即可获取原生指针使用,无需手动释放
原有实现的问题说明
- 第一个实现的内存泄漏根源是内存所有权不清晰,函数内申请的动态内存没有明确的释放规则,很容易被调用者忽略导致泄漏。
- 第二个临时方案属于严重的未定义行为:你返回了栈上分配的数组地址,函数执行结束后栈空间会被系统回收,后续访问这个地址的内容完全不可控,只是当前测试场景下没有触发崩溃而已,在复杂逻辑下必然会出现乱码、程序崩溃等问题。
内容的提问来源于stack exchange,提问作者UniBoring
相关产品推荐
相关产品推荐

