質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

2回答

2630閲覧

VB.Netで作成したアプリのメモリリークを解決したい

ksmemleak

総合スコア1

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

1クリップ

投稿2023/09/03 15:13

編集2023/09/03 15:34

実現したいこと

VB.Netで作成したアプリのメモリリークを解決したい。
・タスクマネージャー上のワーキングセットを肥大化していくためこれを抑制、もしくは一定期間で破棄を行いたい。

前提

・.Net Framework 4.5 をターゲットフレームワークとしています。
・Windowsサービスとして構成し、処理クラスをサービスからインスタンス化して実行しています。
・処理クラスはThreading.Timerを使ってファイル監視を行い、ファイルが存在した場合に内容を読み込んでODBCによりDB更新を行っています。

発生している問題・エラーメッセージ

現象としてはファイル(20KB~78KB)を処理するにともなってタスマネージャー上のワーキングセットが肥大化しており、これがサーバー実行上3日間ぐらいの稼働(原則24時間稼働)で10GBを超えることから何とかリークを解消したいという思いです。
開発端末(Windows10)では完全無風状態が続くと、タスクマネージャー上のワーキングセットが減少しますが、顧客環境のWindowsサーバー上では減少しているのかいまいち把握できないのと、もっと早いタイミングで減少させたいという思いです。

【質問事項】
先輩方にお聞きしたいのが、VisualStudio2019のデバッグでメモリの状況を確認しているとプロセスメモリ(MB)が368MB以上にも係わらずスナップショットを取るとヒープサイズは1Mとなっています。
このプロセスメモリの内容調査をしたい場合どのような手法があるでしょうか。
イメージ説明

該当のソースコード

VB.Net

1 2### 試したこと 3・Fileへのアクセス時のUsing使用 4・ODBCオブジェクトUsing使用 5・内部変数の破棄 6・内部のStringクラスの使用をやめる検討 7・内部クラスでDisposeを実装してクラス変数のDictionaryのすべてのキーのRemoveを実行する。 8・関数で使用している内部変数をFinallyブロックを作成して破棄 等...

###追記
WinDBGを使用してダンプの解析を行ってみた内容です。
・ヒープに割り当たっているメモリ(heap -s 0)の予約、コミットはタスクマネージャーと近しい数値が見えました。
・割り当てされたオブジェクトサイズごとの一覧(heap -stat -h 0)ではやはり小さい数字の合計しか取れませんでした。
・リークしたヒープ(heap -l)を取ると確かに大量にCountのメモリが検出されますがトータルサイズですと、タスクマネージャーのワーキングセットの大きさにはならず。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

メモリ使用量はこちらのツールが見やすいです。
https://learn.microsoft.com/ja-jp/sysinternals/downloads/vmmap

C++CLIですが何やら似たような現象で質問している方がいます。
https://teratail.com/questions/196535

こちらの方はODBCドライバーのバグだとか。
https://stackoverflow.com/questions/13513224/filemakers-odbc-driver-doesnt-release-handles-memory-leak

VSのデバッガでのヒープは小さいので、何となくODBCドライバーとかアンマネージドな世界でハンドルリークしてる様な気がしますね。

投稿2023/09/04 14:54

naitou

総合スコア141

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ksmemleak

2023/09/04 20:25

dn_さま 回答ありがとうございます。類型質問を探しきれておらず誠に申し訳ございません。 「こちらの方はODBCドライバーのバグだとか。」のまさにこちらでした、ODBCConnectionをDisposeしてもドライバー側でハンドルを開放しないとのことで、ALOCする場合は、そのまえにFREEを実施せよなど開発元からコメントが出てましたが、、、、 試しにコネクションを内部で保持して使いまわすようにしたら、メモリの肥大化を抑えることができました。 そもそもDBコネクションを大量に作成するなという事かもしれませんが、、、Disposeはうまく動かしてほしかったです。。 >VSのデバッガでのヒープは小さいので、何となくODBCドライバーとかアンマネージドな世界でハンドルリークしてる様な気がしますね。 おっしゃる通りで、有償版のメモリプロファイラツールのトライアルで確認しましたが、やはり.Netのヒープは抑えられていました。最初から100%の精度ではなかったですが、「アンマネージドな世界」のリークについて経験が足りずにそこにたどり着けてませんでした。。。途中のドキュメントはしばしば書いてあったので今後に生かそうと思います。 大変助かりました。ありがとうございました。
guest

0

GC にもサーバーモードとワークステーションモードがあります。
app.config で GC の設定を調整できますので、いろいろいじってみてください。

xml

1<?xml version="1.0" encoding="utf-8" ?> 2<configuration> 3 ... 4 <runtime> 5 <gcServer enabled="false"/> 6 </runtime> 7</configuration>

「ガベージ コレクションの実行時構成オプション」
https://learn.microsoft.com/ja-jp/dotnet/core/runtime-config/garbage-collector
いちばん後ろの GCConserveMemory は結構有効な気がします。

気になった点
・ソースの修正について、上2つはアンマネージが絡むので有効と思います。
が、他の部分でマネージなものを扱っているのであれば、あまり有効とは思えません。
というのは変数に Nothing を代入しても、即時解放されるわけでなく、GC が動いた時だからです。
・ODBCオブジェクトとは何でしょうか?ADO.NET を使わず独自実装したものですか?
専用の Data Provider があるならそちらを使ったほうが良いです。

投稿2023/09/03 19:35

編集2023/09/03 22:57
KOZ6.0

総合スコア2696

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ksmemleak

2023/09/04 02:34 編集

KOZ6.0さま 早速のご返信ありがとうございます。「ガベージ コレクションの実行時構成オプション」について熟読して検討いたします。GCConserveMemoryを使えると嬉しいと感じます。 >・ODBCオブジェクトとは何でしょうか?ADO.NET を使わず独自実装したものですか? >専用の Data Provider があるならそちらを使ったほうが良いです アプリで操作しているのが下記クラスとなっています。ラップするクラスにIDisposableを付けてDisposeメソッドを呼び出すようにしています。  System.Data.Odbc.OdbcConnection  System.Data.Odbc.OdbcTransaction WindowsOS側で「ODBCデータソース」に登録するのはDB開発元から提供されているODBCドライバーとなっています。
ksmemleak

2023/09/04 20:28

KOZ6.0さま 原因としては、DB開発元が提供しているODBCドライバーの仕様によりリークが発生しておりました。(コネクションオープン後、Disposeを掛けてもハンドルが解放されないとの事でした。) しかし今回教えていただいたGCの仕組みや構成オプション等新たな知見をいただき感謝が絶えません。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問