MSDN docs状态:


  lpFilename [输出]
  
  指向缓冲区的指针,该缓冲区接收模块的标准路径。如果路径的长度小于nSize参数指定的大小,则函数将成功执行,并且路径将以空终止的字符串形式返回。
  
  如果路径的长度超过nSize参数指定的大小,则函数将成功执行,并且字符串将被截断为nSize个字符,包括终止的空字符。
  
  Windows XP:字符串被截断为nSize个字符,并且不以null结尾。


这是模棱两可的。我是否要解释为该字符串在Windows XP上永远不会以null终止?还是当字符串被截断时它不是仅以null终止?

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

最佳答案

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


  如果函数成功,则返回值是复制到缓冲区的字符串的长度,以字符为单位,不包括终止的空字符。如果缓冲区太小而无法容纳模块名称,则字符串将被截断为nSize个字符(包括终止空字符),该函数返回nSize,并且该函数将最后一个错误设置为ERROR_INSUFFICIENT_BUFFER。
  
  Windows XP:如果缓冲区太小而无法容纳模块名称,则该函数返回nSize。最后一个错误代码仍为ERROR_SUCCESS。如果nSize为零,则返回值为零,最后一个错误代码为ERROR_SUCCESS。
  
  如果函数失败,则返回值为0(零)。要获取扩展的错误信息,请调用GetLastError。


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

如果您有完整的路径(ERROR_SUCCESS)和return-value == nSize,则不应假定该路径以null结尾。

在我看来,这表明永远不要假设它是空终止的。接口损坏。您发送给函数的缓冲区应该比nSize大1个字符。然后,您可以进行空终止。

从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;
}

关于c++ - GetModuleFileName的边缘情况不清楚,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38352115/

10-10 21:24