4

フィールドの順序が異なるため、64 ビット アプリの場合、WSAData 構造体の .NET Framework バージョンとネイティブ Win32 バージョンの間に不一致があります。C# ベースの製品で使用するために .NET バージョンをコピーしましたが、同僚が私がメモリ破損を引き起こしたのではないかと心配しています。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 Frameworkのマネージ バージョンは次のとおりです。

[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
                                               );
4

2 に答える 2

4

確かに、これは正しくありません。.NET Framework はそれを回避します。構造体のサイズは依然として正しい (32 ビット モードで 400 バイト、64 ビット モードで 408 バイト) ため、メモリの破損は発生しません。そして、返された情報を実際に使用することはありません。使用していれば、バグを確実に見つけていたはずです。

connect.microsoft.com でバグを報告できますが、彼らが急いで修正することはないと思います。

于 2015-03-22T19:46:42.257 に答える
1

はい、構造が間違っています...間違った構造と正しい構造を使用してテストできます。

[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 はこれらのさまざまなフィールドをすべて使用しないため、問題はありません (説明が必要な理由は何ですか?) 使用される方法は Ansi 1 つ ( CharSet=CharSet.Ansi) であり、すべての Ansi 文字は Unicode で有効な文字です。

于 2015-03-22T19:46:13.800 に答える