来自GetVolumeInformation()的不同磁盘序列号结果

问题描述 投票:2回答:3
DWORD disk_serialINT[MAX_PATH + 1];
GetVolumeInformationA(NULL, NULL, NULL, disk_serialINT, NULL, NULL, NULL, NULL);
char* disk_serialANSI;
sprintf(disk_serialANSI, "%d", disk_serialINT);
std::string HDDserial = disk_serialANSI;

这是我获得硬盘序列号的代码段,但是问题是,每次程序执行时,值都是不同的。有人可以解释吗?

已解决:

DWORD disk_serialINT;
GetVolumeInformationA(NULL, NULL, NULL, &disk_serialINT, NULL, NULL, NULL, NULL);
std::string HDDserial = std::to_string(disk_serialINT);

谢谢。

c++ winapi disk hardware-id
3个回答
7
投票

这两行将为您提供undefined behavior

char* disk_serialANSI;
sprintf(disk_serialANSI, "%d", disk_serialINT);

您声明了一个指针变量,但实际上并未使其指向任何地方。未初始化的局部变量具有不确定的值(实际上,它似乎是随机的),并且通过使用该未初始化的指针,您不知道where sprintf调用将写入。


由于您使用C ++进行编程,因此有两种解决方案。

  • 老式的方法是使disk_serialANSI成为字符数组,其大小足以容纳数字(包括字符串终止符)。另一种方法是手动为指针分配内存,然后在完成使用后再次释放该内存。

  • 使用std::ostringstream格式化数据并获得std::ostringstream

  • 使用std::string直接转换为字符串。

  • 使用std::to_string


2
投票

在Joachim所说的之上,您没有正确传递序列号。您应该将指针传递给单个值。

std::to_string

在您的代码中,这与您在此处所做的事情很复杂:

Boost Lexical cast

忽略Joachim的答案所涉及的未初始化变量DWORD disk_serialINT; GetVolumeInformationA(NULL, NULL, NULL, &disk_serialINT, NULL, NULL, NULL, NULL); ,您正在传递指向sprintf(disk_serialANSI, "%d", disk_serialINT); 格式字符串的指针。一旦将disk_serialANSI更改为单个值,情况会更好。但是,您要将无符号值传递给单个格式的字符串。

是时候放弃这些陈旧的C格式化功能,而使用C ++标准库在整数值和文本之间进行转换了。

最后要强调的一点是,您必须检查对Win32 API的调用的返回值。您不知道函数调用是否成功。您不得以为是。这些全部包含在文档中:"%d"

此程序将打印包含当前目录的卷的序列号:

disk_serialINT

0
投票

如果有人来查看此代码,这里的解决方案就是我的看法:

问题1

https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993.aspx
  • [仅在需要时声明一个#include <Windows.h> #include <iostream> int main() { DWORD disk_serialINT; if (!GetVolumeInformationA(NULL, NULL, NULL, &disk_serialINT, NULL, NULL, NULL, NULL)) { std::cout << "Failed: " << GetLastError() << std::endl; return 1; } std::cout << "Current directory volume serial numnber: " << std::hex << disk_serialINT << std::endl; return 0; } 值的数组。
  • 使用DWORD disk_serialINT[MAX_PATH + 1]; 宏(并向其添加1)而不了解其用途。
  • 不知道类型(当DWORD类型为unsigned时为变量MAX_PATH命名)。
  • 不了解问题域(当变量INT实际上是volume序列号时将其命名)。

问题2

DWORD
  • 无错误处理(不检查函数返回值是否失败)。
  • 不理解按值传递参数和按引用传递参数之间的区别(不传递disk_serial变量的地址)。

问题#3

GetVolumeInformationA(NULL, NULL, NULL, disk_serialINT, NULL, NULL, NULL, NULL);
  • 不了解数组和指针之间的区别。
  • 不了解静态分配和动态分配之间的区别。

问题4

disk_serialINT
  • 使用未初始化的变量char* disk_serialANSI;
  • 使用错误的变量类型(使用sprintf(disk_serialANSI, "%d", disk_serialINT); 数组,或保留指针但分配内存,然后释放它)。>>
  • 不了解问题域(卷序列号使用错误的格式,应该为disk_serialANSI。]
  • 未使用char的安全版本。
  • 问题5

%08lX
  • 没有充分理由混合C和C ++。
  • 换句话说,您所有典型的初学者程序员都犯了错误。希望他们在此期间能学到更多,而不仅仅是在Stack Overflow上找到问题的答案。

[David Heffeman上面已经提供了C ++解决方案,所以为了回答完整,这里是等效的C解决方案:

sprintf
© www.soinside.com 2019 - 2024. All rights reserved.