一次强制转换就能把看似普通的代理设置辅助程序变成与体系结构相关的失败:

current = (IntPtr)((int)current + optionSize);

这段代码在加上下一个结构的大小之前,先把本机地址收窄为 32 位整数。64 位进程可能持有无法容纳的地址。根据转换和取值的不同,结果可能是溢出异常或无效地址。把构建改回 x86 也许能掩盖错误,但会让 interop 实现依赖这种绕行做法。

让地址保持指针大小。例如,遍历已分配的数组可以使用:

IntPtr item = IntPtr.Add(buffer, checked(index * optionSize));

偏移量仍是整数,地址本身不会从中挤过。分配大小和索引仍必须有效。

然后检查周围的声明

WinINet 的每连接选项包含一个联合,其成员包括 DWORD、字符串指针和 FILETIME。指针字段需要 IntPtr;DWORD 字段仍是 32 位。本机对齐很重要,因此把所有整数换成 64 位整数或强制使用紧凑布局并不是可靠的修复。

遍历数组时使用封送后的结构大小,一致地匹配 ANSI 或 Unicode 声明,并单独跟踪每次分配。释放选项结构块并不会自动释放别处分配、并由这些结构引用的字符串。

最后,把设置作用域的问题与内存正确性分开。修复转换并不能证明辅助程序所选的 WinINet 选项只影响一个控件、一个进程或当前用户的设置。在沿用旧示例的其余部分之前,请先核实该 API 行为。如果它还会发送刷新通知,请按预期作用域选择它们。

相关文章