0

MSDN 文档状态:

lpFilename [输出]

指向接收模块的完全限定路径的缓冲区的指针。如果路径的长度小于 nSize 参数指定的大小,则函数成功并且路径作为以空字符结尾的字符串返回。

如果路径的长度超过了 nSize 参数指定的大小,则函数成功并且字符串被截断为 nSize 个字符,包括终止空字符。

Windows XP:字符串被截断为 nSize 个字符并且不是以空值结尾的。

这是模棱两可的。我是否可以解释为该字符串在 Windows XP 上永远不会以空值结尾?或者当字符串被截断时它不是以空结尾的?

如果有人知道措辞更好的参考资料,或者在某处运行 Windows XP 并且可以简单地测试行为,我将不胜感激。

4

1 回答 1

1

我认为您需要在上述段落的上下文中阅读该行:

如果函数成功,则返回值是复制到缓冲区的字符串的长度,以字符为单位,不包括终止的空字符。如果缓冲区太小而无法容纳模块名称,则字符串将被截断为 nSize 个字符,包括终止空字符,函数返回 nSize,并且函数将最后一个错误设置为 ERROR_INSUFFICIENT_BUFFER。

Windows XP:如果缓冲区太小而无法容纳模块名称,则函数返回 nSize。最后一个错误代码仍然是 ERROR_SUCCESS。如果 nSize 为零,则返回值为零,最后一个错误代码为 ERROR_SUCCESS。

如果函数失败,则返回值为 0(零)。要获取扩展错误信息,请调用 GetLastError。

然后使用返回值和对 GetLastError() 的调用的组合来确定您是否有完整的路径。

如果你有一个完整的路径 ( ERROR_SUCCESS) 并且return-value == nSize你不应该假设它是空终止的。

在我看来,这主张永远不要假设它是空终止的。接口坏了。您发送给函数的缓冲区应该比 nSize 大一个字符。然后你可以空终止。

从 c++11 开始,std::basic_string<TCHAR>保证附加一个尾随零,所以这样的事情应该做得很好:

std::basic_string<TCHAR> better_get_module_filename(HMODULE hModule)
{
    std::basic_string<TCHAR> result(128, 0);
    DWORD err = ERROR_SUCCESS;
    do {
        auto actual = GetModuleFileName(hModule, std::addressof(result[0]), result.size());
        err = GetLastError();
        if (actual == 0) {
            throw "error of choice, wrapping err";
        }
        result.resize(actual);
    } while(err == ERROR_INSUFFICIENT_BUFFER);
    return result;
}
于 2016-07-13T13:13:36.170 回答