چرا یک کمککننده قدیمی پروکسی WinINet در ساخت 64-بیتی میشکند
بریدن اشارهگر را در نمونههای interop پروکسی C# تشخیص دهید و پیش از استفاده دوباره، چیدمان ساختارها و مالکیت حافظه را بررسی کنید.
یک تبدیل میتواند یک کمککننده ظاهراً معمولی تنظیمات پروکسی را به خرابی وابسته به معماری تبدیل کند:
current = (IntPtr)((int)current + optionSize);
آن کد یک نشانی بومی را پیش از افزودن اندازه ساختار بعدی به عدد صحیح 32-بیتی تنگ میکند. یک فرایند 64-بیتی میتواند نشانیهایی را نگه دارد که جا نمیشوند. بسته به تبدیل و مقدار، نتیجه میتواند استثنای سرریز یا نشانی نامعتبر باشد. بازگرداندن ساخت به x86 میتواند خطا را پنهان کند، اما پیادهسازی interop را به آن راهحل موقت وابسته میگذارد.
نشانیها را به شکل اندازه اشارهگر نگه دارید. مثلاً برای پیشروی در آرایهای که از قبل تخصیص یافته میتوان از این استفاده کرد:
IntPtr item = IntPtr.Add(buffer, checked(index * optionSize));
افست عدد صحیح میماند؛ خود نشانی از میان یکی فشرده نمیشود. اندازه تخصیص و اندیس هنوز باید معتبر باشند.
سپس اعلانهای اطراف را بررسی کنید
گزینههای WinINet برای هر اتصال شامل یک union است که اعضای آن یک DWORD، یک اشارهگر رشته و یک FILETIME را در بر میگیرد. فیلدهای اشارهگر به IntPtr نیاز دارند؛ فیلدهای DWORD 32-بیتی میمانند. تراز بومی مهم است، بنابراین جایگزینی هر عدد صحیح با عدد صحیح 64-بیتی یا تحمیل چیدمان بستهبندیشده تعمیر درستی نیست.
هنگام پیمایش آرایه از اندازه ساختار پس از marshaling استفاده کنید، اعلان ANSI یا Unicode را بهطور سازگار تطبیق دهید و هر تخصیص را جداگانه پیگیری کنید. آزادکردن بلوک ساختارهای گزینه، رشتههایی را که جای دیگری تخصیص یافتهاند و این ساختارها به آنها ارجاع میدهند بهطور خودکار آزاد نمیکند.
در پایان، مسئله دامنه تنظیمات را از درستی حافظه جدا نگه دارید. تعمیر یک تبدیل ثابت نمیکند که گزینه انتخابی WinINet فقط بر یک کنترل، یک فرایند یا تنظیمات کاربر جاری اثر میگذارد. پیش از پذیرش بقیه یک نمونه قدیمی، آن رفتار API را بررسی کنید. اگر اعلانهای بازخوانی هم میفرستد، آنها را برای دامنه موردنظر انتخاب کنید.