こんばんわ、なべ使いと申します。
Windows7でVC++2010expressの環境で現在、前任者からPICマイコンとUSB通信を行うアプリケー
ションを引き継いで設計しています。
PICマイコンから100ms毎にデータを抜き取りアプリで表示し、logとしてCSVに保存しています。
段々とメモリ(プライベートワーキングセット)が増えいき、10分を過ぎるとlogのデータ数がす
くなくなっていきます。
原因として、メモリリークではないかと思い、動的メモリの確保しているmalooc、newを調べる
とUSBがPICとの接続するときだけに使用しているだけで、そのほかに動的なメモリは使用してい
なく、どのような原因でこのようなことが起きるのでしょうか。
PICとの通信で常時使用するのは、書き込みは、WriteFile(WriteHandle, &OutputPacketBuffer,
65, &BytesWritten, 0);関数を用いて、読み込みは、ReadFile(ReadHandle,
&InputPacketBuffer, 65, &BytesRead, 0);関数を使用し、バッファは、OutputPacketBuffer、
InputPacketBuffer共にグローバル変数としています。
情報として不足がありましたら、追加いたしますので
すみませんが、ご教示の程宜しくお願い致します。
回答ではありません。あしからず。
手元にExpressもCommunityも無くて確かめられないのですが、
デバッグビルドならばメモリーリークを検出できたと記憶してますが、
Expressはできなかったでしたっけ。
一応メモリリーク検出できるか以下のサイトを参考して、やってみましたが、出力表示
は、「プログラム '[6844] **.exe: マネージ (**)' はコード 0 (0x0) で終了
しました。」とだけしか出ませんでした。
メモリリーク検出が行われていたらMemoryLeakCheck.exeなどと出るらしいので・・・
多分Expressでは、出来ないのではないかと思ってます。また、2008expressは出来ない
と記載されていました。
メモリリーク参考HP: http://urashita.com/archives/1271
2008express未対応参考HP: https://msdn.microsoft.com/ja-
jp/library/e5ewb1h3(v=vs.90).aspx
すみませんが宜しくお願い致します。
うーーん、
PICの形名はなんですか?
旧型PICだと、USBN9604等を使っている場合があります。
USBN9604等を使ったUSBのドライバーは、WINDOWS7に対応しないと思います。
確かめてみたほうがいいですね。
マイクロチップ社のドライバーやWINUSBを使っていればokです。
WriteFile/ReadFileはオーバラップI/Oで使った方がいいですね。
処理が終わらないうちにウインドウが閉じると、メモリーリークが発生します。
ITOさんありがとうございます。
PICの形名は、PIC24FJ64GB00になります。ドライバは、多分マイクロチップ社のを使用
していると思われます。前任者から引き継ぎの為、確かな情報はありませんが・・・
WriteFile/ReadFileのオーバラップI/Oについては、ちょっと確認してみます。
ITOさん
ちょっと教えてください。
WriteFile/ReadFileのオーバーラップI/Oは、まだ未実施なんですが、オーバーラップしない場
合は、処理が終わらないうちにウインドウが閉じるとメモリリークが発生するとありますが、詳
しく教えて頂けないでしょうか。
オーバーラップしないと、ずーと待ち状態になるからウインドウは閉じない様に思えるのです
が、違うのでしょうか。
宜しくお願い致します。
>オーバーラップしないと、ずーと待ち状態になるからウインドウは閉じない様に
>思える>のですが、違うのでしょうか。
ソフトの利用方法で変わると思いますが、通常待ち状態にならないように通信処理は
スレッドで動かします。
スレッドで動かすと待ち状態でもウインドウは閉じてしまうので、メモリリーク
が発生してしまいます。
なので、WriteFile/ReadFileは、待ち状態にならないようオーバーラップI/Oで
動かします。
ITOさんありがとうございます。
スレッドで動かすと待ち状態でもウインドウが閉じてしまうからオーバーラップI/Oによりメモ
リリークを発生させないようにすると言うことなんですね。
なるほど、ありがとうございます。
今回、私が引き継いだソフトは、特にスレッドは使ってない様に思えます。PICとのデータ通信
が主で、そのデータを演算して、グラフ表示してlogとして保存するようなものです。あとは、
ボタン操作でpic側の設定変更になります。
スレッドでないソフトでメモリ(プライベートワーキングセット)が増えていく原因は何でしょう
かね。
すみませんが、ご教示の程宜しくお願い致します。
通信が主なのにグラフ表示も行う、処理を考えるとスレッド化も考慮に入れたほうが
いいと思います。
僕は使ったことがないですが、winusbで専用関数を使う方法があるみたいです。
それを使えば、オーバーラップI/Oを使わずにタイムアウト機能を設けることが出来る
可能性はあると思います。
>スレッドでないソフトでメモリ(プライベートワーキングセット)が増えていく原因は何
>でしょうかね。
この処理状況だと通信処理で受信したデータを new・malloc等で確保したメモリーに
一時保存している可能性がありますね。
そこらへんのメモリ処理はどうなっていますか?
グラフ表示もしているなら、グラフ表示の方が原因という可能性もありませんか。
仮にグラフ表示部分をコメント化しても現象は変わりませんか?
ITOさん、みいさんありがとうございます。
タイマーイベントの中でWriteFile/ReadFileで通信処理したあとは、特にnew、malloc
はしないローカルの配列に入れてます。
そこから、ファイルへ書込み(StreamWriter()関数)、グラフ描画(AddXY()関数)を行っ
ています。
グラフをコメントアウトして、動作させると、今までlogデータは10分過ぎると段々と
少なくなって行きましたが、1時間半経ってもデータ数は変わらなくなりました。
ただ、やはりメモリは、少しづつ増えて行ってます。
データ数が変わらくなったのは、処理内容が多すぎてタイマーイベントに追いついてい
けてなかったからでしょうか。
これをマルチスレッドにするとデータ数を減らさず、通信が出来よう様になるのでしょ
うか。
マルチスレッドは、使ったことがないのですが、難しいのでしょうか。
> グラフをコメントアウトして
AddXY()関数をコメントアウトされたのでしょうか。
AddXYし続けていったら内部保持のデータ量が
増えていきますので、使用メモリはどんどん増えていきます。
グラフには全部のデータを表示しているのでしょうか。
であれば、マルチスレッドにして描画処理の負荷を
通信に影響しないようにしても、どんどん負荷&使用メモリ
が増加していつか通信に影響を及ぼす可能性があります。
一定期間のものだけ描画するのであれば一定量を超えたら
一旦クリアして表示期間分だけセットする等工夫が必要です。
> 一定期間のものだけ描画するのであれば
訂正
一定期間のものだけ描画するようにして
みいさんありがとうございます。
グラフ描画のコメントアウトは、AddXY()関数になります。
ずーとAddXY()関数を続けると使用メモリが増えていく・・・
コメントアウトしたのに、メモリが増えて行くのとは別に、このグラフ描画でも増えて
いたということですね。
このグラフ描画を一定期間のものだけを描画するようにすると、このグラフ描画でのメ
モリが増えていくことがなくなるということでしょうか。
今、データが常に末尾に追加されているのを一定期間毎に描画するようにすると言うこ
とでしょうか。
うーーん、
グラフの場合、規模を考慮して最大メモリ容量を決めてしまうのも手です。
多い場合はnew等を使うことも必要です。
容量可変型の変数を使うと失敗しやすいと思います。
データを何件・何千件表示するか利用者と決めておいた方がいいです。
必要な件数まできたら、保存を行うようにして、また0件から取得する。
データはCSV形式でエクセル等で使えるようにしておけばいいと思います。
以上でどうでしょうか?