【问题标题】:Getting Access Violation Error using GetFileVersionInfo使用 GetFileVersionInfo 获取访问冲突错误
【发布时间】:2013-10-07 13:04:46
【问题描述】:
    DWORD dwHandle;

    DWORD dwSize = GetFileVersionInfoSizeEx( FILE_VER_GET_NEUTRAL , strFilePath.c_str() , &dwHandle );
    if( dwSize == 0 )
        break;
    pVersionInfo = new BYTE[ dwSize ];
    bRetVal = GetFileVersionInfoEx( FILE_VER_GET_NEUTRAL , strFilePath.c_str() ,dwHandle , dwSize , &pVersionInfo );
    if( bRetVal == false )
        break;
    UINT uLen;
    VS_FIXEDFILEINFO *pFileInfo;

    bRetVal = VerQueryValue( &pVersionInfo , L"\\" , (LPVOID *)&pFileInfo , &uLen );

    if( bRetVal == false )
        break;
    DWORD dwFileVersionMS = pFileInfo->dwFileVersionMS;
    DWORD dwFileVersionLS = pFileInfo->dwFileVersionLS;

    DWORD dwLeftMost     = HIWORD(dwFileVersionMS);
    DWORD dwSecondLeft   = LOWORD(dwFileVersionMS);
    DWORD dwSecondRight  = HIWORD(dwFileVersionLS);
    DWORD dwRightMost    = LOWORD(dwFileVersionLS);

    strVersion.sprintf( L"%u.%u.%u.%u", dwLeftMost , dwSecondLeft , dwSecondRight , dwRightMost );
}while(0);
if( pVersionInfo )
    delete []pVersionInfo;
return bRetVal;

在调试此代码时,我在删除语句处遇到访问冲突错误。 .谁能告诉我做错了什么。

【问题讨论】:

  • 我感觉不好更正标题,“访问暴力”比“访问违规”更糟糕。

标签: c++ visual-c++


【解决方案1】:

错误是您将指向已分配数据块的指针作为VerQueryValue 的第一个参数传递,这导致您将错误的地址传递给函数。这会导致未定义的行为,因为VerQueryValue 从内存中不应读取/写入的某处读取数据并将数据写入其中。

解决办法是这里不要使用address-of操作符。


更新:你对 GetFileVersionInfoEx 函数调用做同样的事情。不要将地址运算符用于pVersionInfo

【讨论】:

  • 需要指定哪个 'address-of' 运算符才能使这个答案有帮助...我认为您的意思是 pVersionInfo 而不是 &pVersionInfo
  • 看起来对GetFileVersionInfoEx的调用同样是错误的!
【解决方案2】:

错误在一行

bRetVal = GetFileVersionInfoEx( FILE_VER_GET_NEUTRAL , strFilePath.c_str() ,dwHandle , dwSize , &pVersionInfo );

正确的调用应该是

bRetVal = GetFileVersionInfoEx( FILE_VER_GET_NEUTRAL , strFilePath.c_str() ,dwHandle , dwSize , pVersionInfo );

来自msdn

BOOL WINAPI GetFileVersionInfoEx(
  _In_        DWORD dwFlags,
  _In_        LPCTSTR lptstrFilename,
  _Reserved_  DWORD dwHandle,
  _In_        DWORD dwLen,
  _Out_       LPVOID lpData
);

函数GetFileVersionInfoEx() 将用版本信息填充lpData(或者,在上面更正的示例中,pVersionInfo)指向的缓冲区。在您的代码中,它将更改指针的值,使其指向内存中的其他位置。

当您调用delete[] 时,它会给您一个异常,因为您的指针的值已更改,它不再是new [] 运算符设置的值。换句话说,您正在尝试释放未动态分配的内存。

【讨论】:

    【解决方案3】:

    Here 是您在另一个线程中的问题的解决方案,带有完整的代码示例,但正如指出的那样,问题是您将指针传递给缓冲区以获取信息的方式错误,不需要@987654322 @运算符。

    这是一个代码片段,您的代码已修复为可以正常工作:

    #include <Windows.h>
    #include <cstdio>
    
    #pragma comment(lib, "version.lib")
    
    void main(int argc, char** argv)
    {
        const wchar_t* strFilePath = L"C:\\Windows\\System32\\kernel32.dll";
        DWORD dwHandle;
        BOOL bRetVal;
        DWORD dwSize = GetFileVersionInfoSizeEx( FILE_VER_GET_NEUTRAL , strFilePath , &dwHandle );
        if( dwSize == 0 )
            return;
        BYTE* pVersionInfo = new BYTE[dwSize];
        bRetVal = GetFileVersionInfoEx( FILE_VER_GET_NEUTRAL , strFilePath , dwHandle , dwSize , pVersionInfo );
        if( bRetVal == false )
            return;
        UINT uLen;
        VS_FIXEDFILEINFO *pFileInfo = NULL;
    
        bRetVal = VerQueryValue( pVersionInfo , L"\\" , (LPVOID *)&pFileInfo , &uLen );
    
        if( bRetVal == false )
            return;
        DWORD dwFileVersionMS = pFileInfo->dwFileVersionMS;
        DWORD dwFileVersionLS = pFileInfo->dwFileVersionLS;
    
        DWORD dwLeftMost     = HIWORD(dwFileVersionMS);
        DWORD dwSecondLeft   = LOWORD(dwFileVersionMS);
        DWORD dwSecondRight  = HIWORD(dwFileVersionLS);
        DWORD dwRightMost    = LOWORD(dwFileVersionLS);
    
        char pVersion[1024];
        sprintf(pVersion, "%u.%u.%u.%u", dwLeftMost , dwSecondLeft , dwSecondRight , dwRightMost );
        if( pVersionInfo )
            delete []pVersionInfo;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多