GetAdaptersInfo และ GetAdaptersAddressess BufferLength Param

ฉันมีรหัสดั้งเดิมใน C ++ ที่นี่ซึ่งมีบางสิ่งที่ฉันไม่เข้าใจ ฉันใช้งานมันใน Visual C++ 2008 Express Edition บนเครื่องที่ใช้ Windows XP

รหัสนี้ใช้ฟังก์ชันบางอย่างของ Windows: GetAdaptersInfo และ GetAdaptersที่อยู่ ฉันรู้ว่าพารามิเตอร์สุดท้ายสำหรับทั้งสองสิ่งนี้เป็นตัวชี้ไปยังขนาดของบัฟเฟอร์ และเนื่องจากเป็น in_out จึงสามารถเปลี่ยนแปลงได้ภายในฟังก์ชัน

คำถามของฉันคือ: ฟังก์ชั่นเหล่านี้ควรเปลี่ยนความยาวบัฟเฟอร์หรือไม่

ในโค้ดที่ฉันมี ทุกครั้งที่เรียกใช้ฟังก์ชันเหล่านี้ ตัวแปรความยาวบัฟเฟอร์จะถูกเตรียมใช้งานเป็นศูนย์ และหลังจากเรียกใช้ฟังก์ชันแล้ว ยังคงเป็น 0


person RCC    schedule 01.07.2009    source แหล่งที่มา


คำตอบ (3)


รหัสของคุณต้องมีลักษณะดังนี้:

// 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!

แก้ไข: ดูคำตอบของ Jeremy Friesner ด้วยว่าทำไมโค้ดนี้ถึงยังไม่เพียงพอ

person RichieHindle    schedule 01.07.2009
comment
ดังนั้น GetAdaptersInfo จะได้ขนาดที่องค์ประกอบ pIpAdapterInfo จะอยู่ในการโทรครั้งแรก จากนั้นในการเรียกครั้งที่สองจะได้รับ Adapter Info จริงหรือไม่ นั่นดูน่าสนใจ. ขอขอบคุณสำหรับการชี้แจง. - person RCC; 01.07.2009
comment
ใช่. เป็นเรื่องปกติสำหรับ Windows API ที่เติมบัฟเฟอร์เพื่อให้ทำงานในลักษณะนี้ - person RichieHindle; 01.07.2009

แน่นอนว่าโค้ดตัวอย่างใน @RichieHindle's answer มีสภาวะการแข่งขัน .... ถ้าขนาดของโครงสร้าง Windows ต้องการคืนให้เพิ่มขึ้นหลังจากการเรียก GetAdaptersInfo() ครั้งแรก แต่ก่อนที่จะเรียก GetAdaptersInfo() ครั้งที่สอง การเรียก GetAdaptersInfo() ครั้งที่สองจะล้มเหลวด้วย ERROR_BUFFER_OVERFLOW เช่นกัน และฟังก์ชันของคุณ จะไม่ทำงาน

ใช่ มันเกิดขึ้นในชีวิตจริง -- ฉันเคยเกิดขึ้นกับฉันมาแล้ว หากคุณต้องการให้โค้ดมีความน่าเชื่อถือ คุณจะต้องเรียก GetAdaptersInfo() แบบวนซ้ำ โดยเพิ่มขนาดบัฟเฟอร์ของคุณหลายเท่าที่จำเป็นจนกว่าการโทรจะสำเร็จ

จะต้องมีวิธีที่ทำให้เกิดข้อผิดพลาดน้อยกว่าในการสร้าง API... น่าเสียดายที่ Microsoft ยังไม่พบ :^ป

person Jeremy Friesner    schedule 01.07.2009
comment
+1 จุดดี. และว้าว คุณโชคร้ายมากที่โดนจับได้! - person RichieHindle; 02.07.2009

อันที่จริงเมื่อใช้ Visual Studio 6 ฉันเคยได้รับจำนวนอะแดปเตอร์โดย:

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

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

ไม่เป็นไร ตัวอย่างเช่น สำหรับอะแดปเตอร์ 2 ตัว Buflen ตั้งค่าเป็น 1280 และ sizeof(IP_ADAPTER_INFO) คือ 640

ตอนนี้ฉันใช้ Visual C++ 2008 Express และผลลัพธ์ของฉันถูกตัดทอนเนื่องจากฟังก์ชันยังคงตั้งค่า Buflen เป็น 1280 แต่ค่าของ sizeof(IP_ADAPTER_INFO) คือ 648!

นี่เป็นจุดบกพร่องหรือฉันพลาดอะไรบางอย่างไป?

person Olivier Bertrand    schedule 31.01.2011
comment
ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันเพิ่งพบปัญหาเดียวกันกับบิลด์ MinGW บางทีนี่อาจช่วยใครบางคนได้ในอนาคต เหตุผลก็คือขนาดของประเภท time_t ดู msdn.microsoft.com /en-us/library/windows/desktop/ - person DrP3pp3r; 11.05.2016
comment
ส่วนสำคัญ: เมื่อใช้ Visual Studio 2005 และใหม่กว่า ประเภทข้อมูล time_t จะมีค่าเริ่มต้นเป็นประเภทข้อมูล 8 ไบต์ ไม่ใช่ประเภทข้อมูล 4 ไบต์ที่ใช้สำหรับสมาชิก LeaseObtained และ LeaseExpires บนแพลตฟอร์ม 32 บิต หากต้องการใช้โครงสร้าง IP_ADAPTER_INFO อย่างถูกต้องบนแพลตฟอร์ม 32 บิต ให้กำหนด _USE_32BIT_TIME_T (ใช้ -D _USE_32BIT_TIME_T เป็นตัวเลือก เป็นต้น) เมื่อคอมไพล์แอปพลิเคชันเพื่อบังคับให้ประเภทข้อมูล time_t เป็นประเภทข้อมูล 4 ไบต์ - person DrP3pp3r; 11.05.2016