控制台在将相同的代码存储为char*之前显示问号



这是一个很长的函数,但关键问题是在char*变量。**在我将其转换为存储数据而不是打印到控制台之前,该函数工作正常。

我试图使用char[]而不是char*,那是当我得到一些缓冲区溢出错误时,所以现在它被分配,它显示??控制台到处都是。char*puts();上的正确连接和使用方法是什么

MySystemInfo Msi;
puts(Msi.getOsInfo());
char* MySystemInfo::getOsInfo()
{
    OSVERSIONINFOEX osver;
    BOOL bOsVersionInfoEx;
    HKEY hKey;
    LONG lRet;
    char* RtTmpOsInfo= (char *) malloc(sizeof(char)*70);
    char* s1=(char *) malloc(sizeof(char)*20);
    char* s2=(char *) malloc(sizeof(char)*50);

    // Try calling GetVersionEx() using the OSVERSIONINFOEX structure.
    // If that fails, try using the OSVERSIONINFO structure.
    ZeroMemory(&osver, sizeof(OSVERSIONINFOEX));
    osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osver)))
    {
        osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        if(!GetVersionEx((OSVERSIONINFO *) &osver))
            return "";
    }

    switch (osver.dwPlatformId)
    {
        //Test for the Windows NT product family.
        case VER_PLATFORM_WIN32_NT:
            if(osver.dwMajorVersion <4> BUFSIZE) return "";
            sprintf( s1,"v%d.%d "+ osver.dwMajorVersion, osver.dwMinorVersion);
            // Test for the specific product family.
            if(osver.dwMinorVersion==0){
                if(osver.dwMajorVersion == 5) sprintf(s2,"Microsoft Windows 2000n");
                else if(osver.dwMajorVersion == 6) sprintf(s2,"Microsoft Windows Vistan");
            }
            else if(osver.dwMinorVersion==1){
                if(osver.dwMajorVersion == 5) sprintf(s2,"Microsoft Windows XPn");
                else if(osver.dwMajorVersion == 6) sprintf(s2,"Microsoft Windows 7n");
            }
            else if(osver.dwMinorVersion==2){
                if(osver.dwMajorVersion == 5) sprintf(s2,"Microsoft Windows Server 2003 familyn");
            }
            else sprintf(s2,"unknown OSn");
        break;
    }
    strcat(RtTmpOsInfo,s1);     
    strcat(RtTmpOsInfo,s2);
    //lRet/* = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Hotfix\Q246009", 0, KEY_QUERY_VALUE, &hKey);
    //  printf("Service Pack 1 (Build %d)n", osver.dwBuildNumber & 0xFFFF);*/
    return RtTmpOsInfo;
}

std::strcat在目标缓冲区中查找空字节。然而,RtTmpOsInfo所指向的缓冲区是未初始化的,所以在它上面调用std::strcat会导致未定义的行为。

代替第一个std::strcat调用,只使用

strcpy(RtTmpOsInfo,s1);

或者,如果你不确定s1是否真的有一个空字节,

strncpy(RtTmpOsInfo, s1, SOME_CONSTANT);
其中SOME_CONSTANT为写入RtTmpOsInfo的最大字节数。

由于您将此问题标记为[c++]而不是[c],我建议您放弃使用难以读取/使用/维护的原始C类字符串缓冲区(以及相关的不安全字符串函数,如strcat),而是使用方便的c++字符串类

例如,您可以使用std::string,您可以返回std::string实例而不是原始的char*(与char*原始指针的生命周期相关的所有问题!)。

您可以使用std::string的重载 operator+ += 以非常直观自然的方式连接子字符串。

或者您可以使用 std::ostringstream 类,使用operator<<的流语义构建整个字符串。

在这种情况下,一旦你的整个字符串组成,你可以只调用 ostringstream::str() 方法来获得一个std::string实例返回给调用者。

这样,你的代码会更简单,更清晰,更少bug。

相关内容

最新更新