スキップしてメイン コンテンツへ

 none
NetApiBufferFree で 例外コード: 0xc0000374 RRS feed

  • 質問

  • お世話になっております。

    Visual Studio 2013 (C#) で、Windowsサービスアプリケーションを作成しています。

    System.Threading.Timer クラスのオブジェクトから呼び出されたコールバックメソッド(TimerElapsed)内で、次のようなコードを書きました。ネットワーク共有フォルダの内容を処理しようとしているものです。

            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public struct SHARE_INFO_2
            {
                [MarshalAs(UnmanagedType.LPWStr)]
                public string shi2_netname;
                public uint shi2_type;
                [MarshalAs(UnmanagedType.LPWStr)]
                public string shi2_remark;
                public UInt32 shi2_permissions;
                public UInt32 shi2_max_uses;
                public UInt32 shi2_current_uses;
                [MarshalAs(UnmanagedType.LPWStr)]
                public string shi2_path;
                [MarshalAs(UnmanagedType.LPWStr)]
                public string shi2_passwd;
            }
    
            [DllImport("Netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            protected static extern int NetShareEnum(
                 string ServerName,
                 int level,
                 ref IntPtr bufPtr,
                 int prefmaxlen,
                 out int entriesread,
                 out int totalentries,
                 ref IntPtr resume_handle
                 );
    
            [System.Runtime.InteropServices.DllImport("netapi32.dll", SetLastError = true)]
            static extern int NetApiBufferFree(
                ref IntPtr bufptr
            );
    
            const int MAX_PREFERRED_LENGTH = -1;
    
    //
    protected void TimerElapsed(object o)
    {
    ...
                IntPtr resume = IntPtr.Zero;
                int current, total;
                IntPtr buf = IntPtr.Zero;
                int ret = NetShareEnum(null, 2, ref buf, MAX_PREFERRED_LENGTH, out current, out total, ref resume);
                if (ret != 0)
                {
                    throw new System.ComponentModel.Win32Exception(ret);
                }
                NetApiBufferFree(ref buf);    // <= ここ
    ...
    }

    Windows 7 (32bit SP1)では問題は発生しないのですが、Windows 2008 R2 (SP1)で実行させると、上記メソッド内のNetApiBufferFree関数の呼び出しで、ntdll.dll の中で異常終了してしまいます。

    • try-catch構文では捕捉できません。
    • NetShareEnumの直後にすぐNetApiBufferFreeを呼び出しても(あいだで何もしなくても)異常終了します。
    • 似た処理をしているNetFileEnumで得たバッファについても同様の異常終了となってしまいます。
    • Windows7とWindows2008R2のどちらのOSの場合でも、欲しい内容はうまく取得できています。

    イベントログには、エラー(Application Error)として次の内容が記録されます。

    ---

    障害が発生しているアプリケーション名: *.exe、バージョン: *、タイム スタンプ: *
    障害が発生しているモジュール名: ntdll.dll、バージョン: 6.1.7601.18247、タイム スタンプ: *
    例外コード: 0xc0000374
    障害オフセット: 0x00000000000c4102

    ---

    障害バケット 、種類 0
    イベント名: APPCRASH
    応答: 使用不可
    Cab ID: 0

    問題の署名:
    P1: opowfc0.exe
    P2: 1.0.2.0
    P3: 545afd58
    P4: StackHash_35cc
    P5: 6.1.7601.18247
    P6: 521eaf24
    P7: c0000374
    P8: 00000000000c4102
    P9: 
    P10: 

    ---

    ヒープが壊れていると 0xC0000374 のエラーとなるとネット上の情報にありましたが、情報取得関数呼び出し後になにもせずにFreeさせてもエラーとなる点で、違うように思います(もしくはすでに壊してしまっているのでしょうか?)。

    どのように調査したら原因がわかりそうでしょうか?もしくは、特定環境下では異常終了するような不具合などがあったりするのでしょうか?

    ご教示下さると幸いです。


    2014年11月6日 5:12

回答

  • なぜNetApiBufferFree()の戻り値を確認しないのでしょうか? 確認していれば正常動作しているように見えるWin7 / 2008R2でもエラーが発生していることはわかるかと。

    [DllImport("netapi32.dll", SetLastError = true)]
    static extern int NetApiBufferFree(IntPtr bufptr);

    となるべきです。

    • 回答としてマーク Always fresh 2014年11月6日 5:54
    2014年11月6日 5:22

すべての返信

  • なぜNetApiBufferFree()の戻り値を確認しないのでしょうか? 確認していれば正常動作しているように見えるWin7 / 2008R2でもエラーが発生していることはわかるかと。

    [DllImport("netapi32.dll", SetLastError = true)]
    static extern int NetApiBufferFree(IntPtr bufptr);

    となるべきです。

    • 回答としてマーク Always fresh 2014年11月6日 5:54
    2014年11月6日 5:22
  • 佐祐理様

    どうも有り難う御座います。大変助かりました。ご指摘通り、引数の型はLPVOID*ではなくLPVOIDであり、関数宣言に誤りがありました。

    修正後うまく動くようになりました。

    関数の戻り値を丁寧にチェックするようにコーディングするよう努めます。

    2014年11月6日 5:57