在将其存储到 char* 之前,控制台会在同一代码上显示问号
console display question marks on same code before storing it to char*
tnis 是一个长函数,但关键问题在 char* 变量中。
**在我将其转换为存储数据而不是打印到控制台之前,该功能运行良好。
我曾尝试使用 char[]
而不是 char*
那是我遇到一些缓冲区溢出错误的时候,所以现在当它被分配时,它显示 ???整个控制台。
在 puts();
上连接和使用 char*
的正确方法是什么
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 2000\n");
else if(osver.dwMajorVersion == 6) sprintf(s2,"Microsoft Windows Vista\n");
}
else if(osver.dwMinorVersion==1){
if(osver.dwMajorVersion == 5) sprintf(s2,"Microsoft Windows XP\n");
else if(osver.dwMajorVersion == 6) sprintf(s2,"Microsoft Windows 7\n");
}
else if(osver.dwMinorVersion==2){
if(osver.dwMajorVersion == 5) sprintf(s2,"Microsoft Windows Server 2003 family\n");
}
else sprintf(s2,"unknown OS\n");
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]
,我建议您放弃使用难以 read/use/maintain 原始 C 类字符串缓冲区(以及相关的不安全字符串函数,如 strcat
),而是使用 方便的 C++ 字符串 class.
例如,您可以使用 std::string
并且可以 return 一个 std::string
实例而不是原始 char*
实例(所有问题都与一个 char*
原始指针!)。
您可以使用 std::string
的重载 operator+
和 +=
连接子字符串,以一种非常直观自然的方式。
或者您可以使用 std::ostringstream
class,并使用流语义构建整个字符串,operator<<
.
在这种情况下,一旦你的整个字符串组成,你可以调用 ostringstream::str()
方法来获得一个 std::string
实例 return发送给来电者。
这样,你的代码会更简单、更清晰、更不容易出错。
tnis 是一个长函数,但关键问题在 char* 变量中。 **在我将其转换为存储数据而不是打印到控制台之前,该功能运行良好。
我曾尝试使用 char[]
而不是 char*
那是我遇到一些缓冲区溢出错误的时候,所以现在当它被分配时,它显示 ???整个控制台。
在 puts();
char*
的正确方法是什么
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 2000\n");
else if(osver.dwMajorVersion == 6) sprintf(s2,"Microsoft Windows Vista\n");
}
else if(osver.dwMinorVersion==1){
if(osver.dwMajorVersion == 5) sprintf(s2,"Microsoft Windows XP\n");
else if(osver.dwMajorVersion == 6) sprintf(s2,"Microsoft Windows 7\n");
}
else if(osver.dwMinorVersion==2){
if(osver.dwMajorVersion == 5) sprintf(s2,"Microsoft Windows Server 2003 family\n");
}
else sprintf(s2,"unknown OS\n");
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]
,我建议您放弃使用难以 read/use/maintain 原始 C 类字符串缓冲区(以及相关的不安全字符串函数,如 strcat
),而是使用 方便的 C++ 字符串 class.
例如,您可以使用 std::string
并且可以 return 一个 std::string
实例而不是原始 char*
实例(所有问题都与一个 char*
原始指针!)。
您可以使用 std::string
的重载 operator+
和 +=
连接子字符串,以一种非常直观自然的方式。
或者您可以使用 std::ostringstream
class,并使用流语义构建整个字符串,operator<<
.
在这种情况下,一旦你的整个字符串组成,你可以调用 ostringstream::str()
方法来获得一个 std::string
实例 return发送给来电者。
这样,你的代码会更简单、更清晰、更不容易出错。