Param GetAdaptersInfo dan GetAdaptersAddressess BufferLength

Saya punya beberapa kode lama di C++ di sini yang melakukan beberapa hal yang saya tidak mengerti. Saya menjalankannya dalam Visual C++ 2008 Express Edition pada mesin yang menjalankan Windows XP.

Kode ini menggunakan beberapa fungsi Windows: GetAdaptersInfo dan DapatkanAdaptersAddressess. Saya menyadari bahwa parameter terakhir untuk keduanya adalah penunjuk ke ukuran buffer dan karena in_out, itu dapat diubah di dalam fungsinya.

Pertanyaan saya adalah: apakah fungsi-fungsi ini seharusnya mengubah panjang buffer?

Dalam kode yang saya miliki, setiap kali fungsi ini dipanggil, variabel panjang buffer diinisialisasi ke nol, dan setelah fungsi dipanggil, tetap 0.


person RCC    schedule 01.07.2009    source sumber


Jawaban (3)


Kode Anda harus terlihat seperti ini:

// First get the desired size.
unsigned long outBufLen = 0;
DWORD dwResult = GetAdaptersInfo(NULL, &outBufLen);
if (dwResult == ERROR_BUFFER_OVERFLOW)  // This is what we're expecting
{
    // Now allocate a structure of the requried size.
    PIP_ADAPTER_INFO pIpAdapterInfo = (PIP_ADAPTER_INFO) malloc(outBufLen);
    dwResult = GetAdaptersInfo(pIpAdapterInfo, &outBufLen);
    if (dwResult == ERROR_SUCCESS)
    {
        // Yay!

Sunting: Lihat juga jawaban Jeremy Friesner mengapa kode ini tidak cukup.

person RichieHindle    schedule 01.07.2009
comment
Jadi GetAdaptersInfo mendapatkan ukuran elemen pIpAdapterInfo pada panggilan pertama, dan kemudian pada panggilan kedua benar-benar mendapatkan Info Adaptor? Itu menarik. Terimakasih atas klarifikasinya. - person RCC; 01.07.2009
comment
Ya. Sangat umum bagi Windows API yang mengisi buffer untuk bekerja dengan cara ini. - person RichieHindle; 01.07.2009

Tentu saja, kode contoh di jawaban @RichieHindle berisi kondisi balapan .... jika ukuran struktur yang ingin dikembalikan Windows bertambah setelah panggilan pertama ke GetAdaptersInfo() tetapi sebelum panggilan kedua ke GetAdaptersInfo(), panggilan kedua ke GetAdaptersInfo() akan gagal dengan ERROR_BUFFER_OVERFLOW juga, dan fungsi Anda tidak akan berhasil.

Ya, hal itu memang terjadi dalam kehidupan nyata -- Saya pernah mengalaminya. Jika ingin kodenya dapat diandalkan, Anda perlu memanggil GetAdaptersInfo() dalam satu lingkaran, meningkatkan ukuran buffer sebanyak yang diperlukan hingga panggilan berhasil.

Pasti ada cara yang tidak terlalu rawan kesalahan untuk membuat API... sayangnya Microsoft belum menemukannya. :^P

person Jeremy Friesner    schedule 01.07.2009
comment
+1 Poin bagus. Dan wow, Anda sangat tidak beruntung karena tertangkap basah! - person RichieHindle; 02.07.2009

Memang, dengan menggunakan Visual studio 6, saya biasa mendapatkan jumlah adaptor dengan:

DWORD drc = GetAdaptersInfo(NULL, &(Buflen = 0L));

if (drc == ERROR_BUFFER_OVERFLOW)
  n = Buflen / sizeof(IP_ADAPTER_INFO);

Tidak apa-apa, misalnya untuk 2 adaptor Buflen disetel ke 1280 dan sizeof(IP_ADAPTER_INFO) adalah 640.

Sekarang saya menggunakan Visual C++ 2008 Express dan hasilnya terpotong karena fungsinya masih menyetel Buflen ke 1280 tetapi nilai sizeof(IP_ADAPTER_INFO) sekarang menjadi 648!

Apakah ini bug atau saya melewatkan sesuatu?

person Olivier Bertrand    schedule 31.01.2011
comment
Saya tahu ini adalah pertanyaan LAMA, tapi saya baru saja mengalami masalah yang sama dengan build MinGW. Jadi mungkin ini membantu seseorang di masa depan. Alasannya adalah ukuran tipe time_t. Lihat msdn.microsoft.com /en-us/library/windows/desktop/ - person DrP3pp3r; 11.05.2016
comment
Bagian penting: Saat menggunakan Visual Studio 2005 dan yang lebih baru, tipe data time_t defaultnya adalah tipe data 8-byte, bukan tipe data 4-byte yang digunakan untuk anggota LeaseObtained dan LeaseExpires pada platform 32-bit. Untuk menggunakan struktur IP_ADAPTER_INFO dengan benar pada platform 32-bit, tentukan _USE_32BIT_TIME_T (misalnya, gunakan -D _USE_32BIT_TIME_T sebagai opsi) saat mengkompilasi aplikasi untuk memaksa tipe data time_t ke tipe data 4 byte. - person DrP3pp3r; 11.05.2016