• ベストアンサー
  • 困ってます

SNMPマネージャAPIでメモリリークしてしまう

初めて投稿します。 ネットワークに接続したプリンタ4台を、SNMPを使って状態監視するソフトを作成しています。以下のソース(文字数制限のため、大半をコメントで記述しています)を実行すると、SnmpMgrRequest()関数内でメモリリークを起こします。 この関数の戻り値はエラーではありません。しかもプリンタ1台のみを監視するとメモリリークしません。この関数をコメント化しても起きません。 SNMPは始めてなので何が悪いのかよくわかりません。 どなたか何かご存知であればご教示お願いします。 開発環境はWindowsXP(SP1) VC++6 SP5を使用しています。 (ソースの拡張子は.cです。) void main(){ while(1){ for (i = 0 ; i < 4 ; i++) { mib=StsGet([プリンタのIPアドレス]); } Sleep(600); } } int StsGet(LPSTR adr) { //SnmpUtilMemAlloc ()でSNMPエージェントのアドレス取得 //SnmpUtilMemAlloc()でコミュニティ取得 //変数バインディングの初期化 //SnmpMgrStrToOid()でOIDを文字列から値に変換 //SnmpUtilMemReAlloc ()で変数バインディングにメモリを割当て //変数バインディングにOIDを追加 //SnmpMgrOpen ()でSNMPマネージャAPIのオープン(タイムアウト:100ms、リトライ:1回) // SnmpMgrRequest()でSNMPマネージャAPIに指定操作(Get)を要求 //SnmpUtilVarBindListFree(),SnmpUtilMemFree()で各変数を解放 //SnmpMgrClose()でSNMPマネージャAPIとの接続を終了 return [プリンタ状態;] }

共感・応援の気持ちを伝えよう!

質問者が選んだベストアンサー

  • ベストアンサー
  • 回答No.2

Musaffah様 Musaffah様は、WinSNMPを使用していないので、 SnmpCleanupは必要ありません。不適切なアドバイスをしてしまい、 申し訳ございませんでした。 サンプルコードありがとうございました。 さっそく、こちらでも確かめてみましたが、 メモリーリークも起きませんし、ちゃんと動作しているようです。 環境は、以下のとおりです。 Windows2000(SP4) VC++6.0(SP6) .NET2003 ダイアログベースのプロジェクトで、ボタンを押すと、 PrnStsGet関数を永久ループで呼び出すようにしました。 VC++6.0, .NET2003両方とも、問題なく動作しますし、 プリンターを2台モニターしても、問題ありません。 ということで、OSとVC++の最新アップデートをお勧めします。 VC++は、Service Pack6を、WindowsXPはSP2にアップデートした 上で、WindowsUpdateを実行して、最新にしたほうがいいでしょう。 会社の同僚で、ネットワーク通信プログラムがフリーズするという 問題が起きていたのですが、SP2にアップデートしたら、解決したようです。 もし、これでも、解決しないようであれば、 新規にテスト用プロジェクトを作成し、このプログラムだけを 実装して、動作テストをすることをお勧めします。 このことにより、問題の切り分けがはっきりするかもしれません。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

お礼の返事が遅くなって申し訳ありません。 WindowsXPをSP2にアップデートしたところ、確かにメモリリークしなくなったことを確認しました! 大変助かりました。ありがとうございました!!

その他の回答 (1)

  • 回答No.1

Musaffah様 WinSNMP APIについては、サンプルコードもないし、 google検索でも、ほどんど引っかからないので、 似たような例は見つかりにくいかもしれませんね。 さて、質問内容についてですが、コメントアウトされた ソースコードでは、こちらも、検証できないので、 自信はありませんが、以下を試してみてはいかがでしょうか? ●SnmpMgrStrToOid関数のあとに、SnmpUtilOidFreeでメモリを開放する。 ●SnmpMgrClose()のあとに、SnmpCleanup()を実行する。 > SnmpMgrRequest()関数内でメモリリークを起こします。 Microsoftが提供したAPIの場合、使い方を誤ると、たまに、 このようなことがおきます。 たとえば、マルチスレッドアプリケーションにおいて、 あるスレッドで初期化したインスタンスやサービスを 別のスレッドが使った場合などに発生したりします。

共感・感謝の気持ちを伝えよう!

質問者からの補足

woody_poco様。 アドバイスありがとうございます! SnmpCleanup()を実行したら2回目以降のチェックができなくなってしまいました(泣)。 質問でコメントアウトした関数を提示します(文字制限オーバーですが・・・すいません)。 SnmpMgrOpen()とSnmpMgeRequest()の初回実行時にのみそれぞれスレッドが1つずつ生成されているのまでは判明しましたが、メモリリークの原因は未だ不明です。 申し訳ありませんがご協力お願い致します。 #define ERR 0x0800 #define Bind RFC1157VarBind #define BindList RFC1157VarBindList #define AsnObj AsnObjectIdentifier int PrnStsGet(LPSTR adr){ UINT iRet=ERR; LPSTR oid=".1.3.6.1.2.1.25.3.5.1.2.1", comname="public"; LPSTR agt,cmnty; BindList bind; Bind *tmpVb; AsnObj obj; LPSNMP_MGR_SESSION se; BYTE req=SNMP_PDU_GET; AsnInteger errSts,errIdx; agt=(LPSTR)SnmpUtilMemAlloc((UINT)(strlen(adr)+1)); strcpy(agt,adr); cmnty=(LPSTR)SnmpUtilMemAlloc((UINT)(strlen(comname)+1)); strcpy(cmnty,comname); bind.list=NULL; bind.len=0; SnmpMgrStrToOid(oid,&obj); bind.len++; tmpVb=(Bind *)SnmpUtilMemReAlloc(bind.list,(sizeof(Bind)* bind.len)); bind.list=tmpVb; bind.list[bind.len-1].name=obj; bind.list[bind.len-1].value.asnType=ASN_NULL; se=SnmpMgrOpen(agt,cmnty,100,1); if(SnmpMgrRequest(se,req,& bind,&errSts,&errIdx)) if(errSts==0){ AsnAny *pAny=& bind.list[0].value; iRet = pAny->asnValue.address.stream[0]; } SnmpUtilVarBindListFree(&bind); SnmpUtilMemFree(agt); SnmpUtilMemFree(cmnty); SnmpMgrClose(se); return iRet; }

関連するQ&A

  • SNMPについて教えてください

    こんばんは。 今度HP社のOpenViewなるネットワーク監視ソフトを 使用することになりました。 そこでSNMPのMIBという用語が出てきました。 例えばOpenViewが、とある機器のCPU使用率を取得する場合、 OIDを指定して、情報を取得すると思っています。 これとは別に、エンタープライズIDという用語があるのですが、 これは、どういった用途や意味を持つでしょうか?。 ※OIDの一部なのでしょうか。 あともう1点、ちょっと話がずれるのですが、 標準SNMPTrapの項目(LinkDownなど)は、 OIDを持っているのでしょうか?。 お手数ですが、アドバイスを頂ければ幸いです。

  • シスコのOIDについて

    シスコのMIBについて教えてください。 シスコルータ(1812J)のCPU使用率を取得したいと考えています。 SNMPサーバは構築済みのため、SNMPサーバ側に設定するCPU使用率 のOIDを知りたいと考えています。 お手数ですが、シスコルータのCPU使用率を取得するためのOIDを教えていただけませんでしょか

  • APIについて

    アプリケーションソフトがが環境変数の値を取得する場合、環境変数を取得するAPI関数が「あそこのレジストリに要求された変数があるから取りに行いこう」という感じでとりに行って、アプリケーションに返してるんでしょうか?

  • LinuxサーバからSNMPレスポンスが返らない

    LinuxサーバにSNMPの設定を行ったところ、自サーバからは問題なくMIB情報を取得できましたが、別マシンのSNMPマネージャーよりGETをしてもレスポンスが返って来ません。 自サーバ:snmpwalk -c public localhost MIB取得OK LinuxサーバでパケットをキャプチャするとGETを受け取った後に、ICMPでDestination Unreachableが発生しています。(宛先は別マシン) なお、snmpd.logには特にログが吐き出されていません。 マシン構成はLinuxサーバがNICを2枚挿しで、それぞれ[192.168.0.100]と[192.168.1.100]を設定し、同じHUBに接続し、別マシンが同じHUBで[192.168.0.253]のアドレスを設定しています。 もちろん、Linuxサーバから別マシンへはpingは問題なく通ります。 レスポンスの返らない理由を教えてください。 また、対処方法が分かれば合わせて教えてください。

  • SNMPでOSの情報を取得

    SNMPでネットワークを監視するソフトを作成しており、そこにWindowsの情報監視(メモリ使用量やHDDの空き等)を追加することになりました。 対象はWin2000~です。 いろいろ調べてWindowsのSNMPサービスだけでは取れない?とあきらめかけていたのですが、Microsoftのページに 「SNMP が不正確なメモリ容量を報告する」がWin2000SP4で修正されたような記述があります。(http://support.microsoft.com/kb/811436/ja) これってWindows2000でSNMPを使ってメモリ容量が取得できるってこと? この辺の詳しい情報および取得方法がありましたら教えていただきたいです。

  • メモリリーク

    VC++ 2010 SP1 MFC使用環境です 現在i以下のサンプルソースをベースに改造しているのですが http://code.msdn.microsoft.com/windowsdesktop/DVD-RW-870205bd その中の関数内で以下の行があります BSTR path = ::SysAllocString(変数)); 改造に当たり関数内で変数の内容を変更させて 同様の処理を複数回行いたいと思っています ここで あれ?  と思ったのが ::SysFreeString(path); 実行してなくてリークしないのか? ということなんですが 試しに BSTR path = ::SysAllocString(変数)); を複数回実行してプログラムを終了してみましたが 出力Windowにはメモリリークは出ていないように感じます その判断が間違ってる可能性は否定できないので質問させていただきました 実際今回のような場合 SysFreeString 関数をコールする必要はないのでしょうか? 仮に今回は必要ないにしても関数自体が存在するということは必要性はあると思うのですが どういったときにコールする必要があるのでしょう

  • SNMPを利用してL3スイッチのメモリ使用率を取得するには

    アライドテレシスのL3スイッチ「CentreCOM 9924T/4SP」を利用しています。 SNMPマネージャからCPUの使用率等に関しては取得できておりますがどのようにOIDを指定すればよいかわからず、メモリに関する情報を取得ができずに困っております。 MIBブラウザなどでMIBを読み込むと free memory「1.3.6.1.4.1.207.8.4.4.3.7.1」となっております。 CPUの場合と同様に搭載数によって語尾に何かしら付加する必要が考えられますがどのようなものでしょうか。 ご存知の方、教えて頂けると幸いです。

  • ネットワーク機器の温度監視

    社内に複数のネットワーク機器がありますが、NetGear社とアライド社の機器の温度を監視出来ればと考えております。 SNMPマネージャーは、TWSNMPを使ってますが、OIDが分かりません。 下記製品の温度監視用のOIDをご存じでしたらお教えください。 NetGear社 GS108Tv2 アライドテレシス社 GS916M よろしくお願いいたします。

  • APIを使用した印刷

    こんにちはsinakuというものですが かなり困っております 現在API関数のみを使用した印刷方法がわかりません どのような順序でプリンタとのやり取りをしてよいやらまったくです そこで教えていただきたいのですが ' まずプリンタ名の取得 GetDefaultPrinter ' 取得したプリンタ名をもとにプリンタのハンドルを取得 OpenPrinter この後から ' プリンタハンドルのクローズ ClosePrinter の間の処理がわかりません いろいろ調べてみたのですが StartDocPrinter GetPrinter などなどまだまだ他にも使用することはわかったのですが 一通りの流れを解説しているようなHPはないでしょうか? または同じようにAPIだけを使用してプリンタの印刷処理を 作られた経験がある方は居ないでしょうか? できれば呼び出すAPIの順序だけでもわかるとどうにかなるのですが 実際にどんな動きで印刷しているのかまったくわからないので よろしくお願いします

  • MIBファイルの見方

    ネットワーク機器の監視をするために、MIBファイルを取得し、情報がある事は確認できたのですが、私の知識不足でOIDが分かりません。 agentPethTemperature OBJECT-TYPE SYNTAX Gauge32 UNITS "DEGREES" MAX-ACCESS read-only STATUS current DESCRIPTION "The temperature measured at this port of the PoE Controller. It is measured in degree celcius." ::= { agentPethPsePortEntry 5 } ここから、OIDを調べる方法はありますでしょうか? ちなみに、NetGear社からダウンロードした、MIBファイルをCentOSの"/user/share/snmp/NetgeraMIB"へ入れて、snmptranslate -On agentPethTemperature を実行しましたが、Unknownでしした。 初歩的な事だとは思いますが、困っておりますのでアドバイス頂けましたら幸いです。