对于64位应用程序来说,.NET框架版本和WSAData结构的原生Win32版本之间存在不匹配,因为字段的顺序不同。我复制了.NET版本,以便在基于C#的产品中使用,一位同事担心我造成了内存损坏。在使用DllImport / PInvoke时,是否存在由于这种不匹配而导致内存损坏的风险?将本机版本封送到托管版本时,是否存在无效内存访问的风险?让我们假设我并不关心实际访问结果WSAData对象的字段。我只想确定我对WSAStartup的调用不会破坏内存或使应用程序崩溃。
这里是WinSock2.h中的本机C++版本。注意,成员的顺序在64位和32位之间是不同的。WSADESCRIPTION_LEN是256,WSASYS_STATUS_LEN是128。
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
#ifdef _WIN64
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
#else
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
#endif
} WSADATA, FAR * LPWSADATA;这是.NET框架中的托管版本
[StructLayout(LayoutKind.Sequential)]
internal struct WSAData {
internal short wVersion;
internal short wHighVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=257)]
internal string szDescription;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=129)]
internal string szSystemStatus;
internal short iMaxSockets;
internal short iMaxUdpDg;
internal IntPtr lpVendorInfo;
}
[DllImport(WS2_32, CharSet=CharSet.Ansi, BestFitMapping=false,
ThrowOnUnmappableChar=true, SetLastError=true)]
internal static extern SocketError WSAStartup(
[In] short wVersionRequested,
[Out] out WSAData lpWSAData
);发布于 2015-03-22 19:46:42
当然,这是不正确的。.NET框架摆脱了它,结构大小仍然正确(在32位模式下的400个字节,64位模式下的408个字节),这样就不会发生内存损坏。而且它实际上不使用任何返回的信息,他们肯定会抓住错误,如果他们这样做。
您可以在connect.microsoft.com上提交该错误,但我怀疑他们是否会急于修复它。
发布于 2015-03-22 19:46:13
是的,结构是错的..。您可以通过使用错误的结构和正确的结构进行测试:
[StructLayout(LayoutKind.Sequential)]
internal struct WSAData
{
internal short wVersion;
internal short wHighVersion;
internal short iMaxSockets;
internal short iMaxUdpDg;
internal IntPtr lpVendorInfo;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
internal string szDescription;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)]
internal string szSystemStatus;
}
WSAData data;
int res = WSAStartup(2 << 8 | 2, out data);
Console.WriteLine("64bits: {0}, Result = {1}, szDescription: {2}, szSystemStatus: {3}", Environment.Is64BitProcess, res, data.szDescription, data.szSystemStatus);但是您没有任何问题,因为.NET可能没有使用所有这些不同的字段(它需要描述做什么?)Unicode转换甚至不会出现问题,因为所使用的方法是Ansi (CharSet=CharSet.Ansi),而且每个Ansi字符都是Unicode中的合法字符。
https://stackoverflow.com/questions/29198807
复制相似问题