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

LPCWSTR数组初始化异常:仅首个成员生效的问题排查

问题:调用RmRegisterResources时仅第一个文件路径生效

我正在编写调用Win32函数RmRegisterResources的代码,该函数接收LPCWSTR[]类型的文件路径列表作为参数。尝试组装LPCWSTR数组时,始终只有第一个成员初始化成功。

我的实现代码如下:

void Test(std::vector<LPCWSTR> input)
{
    size_t vecsize = input.size();
    LPCWSTR* resourcelist = new LPCWSTR[vecsize];

    for (size_t i = 0; i < input.size(); i++)
    {
        LPCWSTR single = input.at(i);
        size_t strsize = wcslen(single);
        resourcelist[i] = new WCHAR[strsize];
        wcscpy_s((WCHAR*)resourcelist[i], strsize, single);
    }

    /*
        The rest of the code...
    */
}  

现象

循环第一次迭代时,第一个字符串复制正常;第二次迭代时wcscpy_s未报错,但无法找到复制后的字符串。最终调用RmRegisterResources时仅第一个复制的字符串生效。

补充说明

我不是开发人员,是一名好奇的系统管理员,正在学习C++。已经连续两天搜索解决方案。根据微软文档,建议一次性传入多个文件名,因为操作成本较高。

编辑1:关于vector input.data()的问题

尝试使用input.data()直接作为参数传给RmRegisterResources时,编译器报错,提示无法将const wchar_t**转换为LPCWSTR*(类型不匹配)。

编辑2:常量数组正常工作

如果用常量值创建数组可以正常调用,示例代码:

LPCWSTR string[2] = { L"Thisisastring", L"Thisisalso" };

但使用LocalAlloc或new关键字分配内存时会出现上述问题。


解决方案

1. 核心问题:内存分配未考虑字符串终止符

wcslen(single)返回的是字符串的有效宽字符数,不包含末尾的\0终止符。你用new WCHAR[strsize]分配的内存刚好容下有效字符,但wcscpy_s会自动添加\0终止符,导致内存越界,破坏后续数组元素的内存,从而出现异常。

2. 修正后的代码

分配内存时给终止符预留1个字符的空间:

void Test(std::vector<LPCWSTR> input)
{
    size_t vecsize = input.size();
    LPCWSTR* resourcelist = new LPCWSTR[vecsize];

    for (size_t i = 0; i < input.size(); i++)
    {
        LPCWSTR single = input.at(i);
        size_t strsize = wcslen(single) + 1; // 加1容纳宽字符终止符\0
        resourcelist[i] = new WCHAR[strsize];
        wcscpy_s((WCHAR*)resourcelist[i], strsize, single);
    }

    // 调用RmRegisterResources...

    // 记得释放内存,避免泄漏
    for (size_t i = 0; i < vecsize; i++)
    {
        delete[] resourcelist[i];
    }
    delete[] resourcelist;
}  

3. 更简洁的替代方案(无需复制内存)

如果input中的LPCWSTR指向的字符串在调用RmRegisterResources期间不会被释放或修改,你可以直接复用这些指针,不需要重新分配内存:

void Test(std::vector<LPCWSTR> input)
{
    if (input.empty()) return;

    // 直接用vector的data()获取数组指针
    LPCWSTR* resourcelist = input.data();

    // 调用RmRegisterResources,传入resourcelist和input.size()即可
    // ...
}

如果之前用input.data()报错,大概率是因为你的input实际类型是std::vector<std::wstring>而非std::vector<LPCWSTR>。这种情况下,可以先把std::wstring的c_str()收集到临时的vector<LPCWSTR>中:

void Test(std::vector<std::wstring> input)
{
    std::vector<LPCWSTR> str_ptrs;
    str_ptrs.reserve(input.size());
    for (const auto& str : input)
    {
        str_ptrs.push_back(str.c_str());
    }

    // 调用RmRegisterResources
    RmRegisterResources(... , str_ptrs.size(), str_ptrs.data(), ...);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 18:40:45