2015-01-28 4 views
2
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; 

Это мой кусок кода, в котором я получаю серийный номер hdd, но проблема в том, что каждый раз, когда программа выполняет это значение, другое. Может ли кто-нибудь объяснить это?Различный серийный номер диска получен из GetVolumeInformation()

РЕШИТЬ:

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

Спасибо.

+2

Три ошибки в этом коде, самое время обновить свои инструменты. –

+1

Какую книгу на C++ вы используете? Он учит вас плохим практикам. –

+0

Это мой частный проект. К сожалению, я не мог найти ни одной книги, из которой я мог бы узнать winapi. – DualCore

ответ

6

Эти две линии дадут вам undefined behavior:

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

Вы объявляете переменную указатель, но на самом деле не делают его точку в любом месте. Неинициализированные локальные переменные имеют неопределенное значение (на практике это будет казаться случайным), и с помощью этого неинициализированного указателя вы не знаете , где вызовет вызов sprintf.


Поскольку вы программируете на C++, существует несколько решений.

  • Старомодная, чтобы сделать disk_serialANSI массив символов, достаточно большой, чтобы держать число (в том числе строки терминатор). Альтернативой является ручное выделение памяти для указателя, а затем освобождение этой памяти еще раз, когда вы закончите с ней.

  • Использование std::ostringstream для форматирования данных и получения std::string.

  • Использование std::to_string для преобразования в строку напрямую.

  • Boost Lexical cast.

2

В дополнение к тому, что говорит Йоахим, вы не передаете серийный номер правильно. Вы должны передать указатель на одно значение.

DWORD disk_serialINT; 
GetVolumeInformationA(NULL, NULL, NULL, &disk_serialINT, NULL, NULL, NULL, NULL); 

В коде это усугубляется тем, что вы делаете здесь:

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

Игнорирование неиницализированные переменной disk_serialANSI, которая охватывает ответ Joachim, вы передаете указатель на строку формата "%d". Как только вы измените disk_serialINT, чтобы быть единым значением, все будет лучше. Однако вы передаете значение unsigned в строку одного формата.

Пришло время отказаться от этих gnarly функций форматирования C и использовать стандартную библиотеку C++ для преобразования между целыми значениями и текстом.

Последним моментом является то, что вы должны проверить возвращаемое значение вызовов API Win32. Вы не знаете, удалось ли вызов функции выполнить. Вы не должны предполагать, что это так.Все это описано в документации к: 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; 
}