以下代码:
#include <iostream>
#include <Windows.h>
using namespace std;
int main ()
{ LPWSTR buffer; //or wchar_t * buffer;
GetModuleFileName(NULL, buffer, MAX_PATH) ;
cout<<buffer;
cin.get();
cin.get();
}
应显示程序执行的完整路径。但是在VS 2012中我得到了错误:
使用未初始化的局部变量'buffer'
代码有什么问题?
答案 0 :(得分:26)
你需要给它一个可以容纳一些字符的缓冲区;
wchar_t buffer[MAX_PATH];
例如,。
答案 1 :(得分:7)
VS正确地指出您正在使用未初始化的缓冲区 - 缓冲区 var是指向WSTR的指针,但它没有使用静态缓冲区初始化,也没有分配。另外你应该记住MAX_PATH通常不够,特别是在具有长路径名的现代系统上。
由于您使用的是C ++,因此使用它的功能是一种很好的做法。我可以假设以下代码:
vector<wchar_t> pathBuf;
DWORD copied = 0;
do {
pathBuf.resize(pathBuf.size()+MAX_PATH);
copied = GetModuleFileName(0, &pathBuf.at(0), pathBuf.size());
} while( copied >= pathBuf.size() );
pathBuf.resize(copied);
wstring path(pathBuf.begin(),pathBuf.end());
cout << path;
不要直接使用wstring作为缓冲区:它没有被定义为在每个实现中都有连续的缓冲区(但通常是)
答案 2 :(得分:0)
这是Win32 API的一个普遍问题,函数会将字符串返回到有限大小的缓冲区中,并且您不确定缓冲区是否足够大以容纳整个字符串。正如kingsb所提到的,即使是MAX_PATH,对于如今的路径而言,也不够好。
为此,我倾向于使用一般的辅助功能:
template <typename TChar, typename TStringGetterFunc>
std::basic_string<TChar> GetStringFromWindowsApi( TStringGetterFunc stringGetter, int initialSize = 0 )
{
if( initialSize <= 0 )
{
initialSize = MAX_PATH;
}
std::basic_string<TChar> result( initialSize, 0 );
for(;;)
{
auto length = stringGetter( &result[0], result.length() );
if( length == 0 )
{
return std::basic_string<TChar>();
}
if( length < result.length() - 1 )
{
result.resize( length );
result.shrink_to_fit();
return result;
}
result.resize( result.length() * 2 );
}
}
GetModuleFileName可以这样使用:
extern HINSTANCE hInstance;
auto moduleName = GetStringFromWindowsApi<TCHAR>( []( TCHAR* buffer, int size )
{
return GetModuleFileName( hInstance, buffer, size );
} );
对于这样的LoadString:
std::basic_string<TCHAR> LoadResourceString( int id )
{
return GetStringFromWindowsApi<TCHAR>( [id]( TCHAR* buffer, int size )
{
return LoadString( hInstance, id, buffer, size );
} );
}