- PR -

VB6で作ったEXEが稀にメモリアクセス違反で不安定,原因はLoadのタイミング?

投稿者投稿内容
檸檬
ベテラン
会議室デビュー日: 2004/04/26
投稿数: 87
投稿日時: 2005-10-04 10:24
 VB6SP5で作ったEXEが毎日似たような処理なのに2ヶ月に1回くらい、メモリアクセス違反で落ちてしまう原因を探しています。
 そこでTCP電文を受信するたびにフォームをNewで作成している箇所が怪しいと思い(作成したフォームは処理が終わるとアンロードします。また、ほぼ常に電文を受信しています。)質問させて頂きました。

 以下のように、接続要求(ConnectionRequest)を受け付けるたびに要求電文処理用のフォームをNewで作成して、再度接続要求(Accept)を受け付ける関数があります。
(一部省略あり)
--------------------------------

Private Sub tcpWSock_ConnectionRequest(Index As Integer, ByVal requestID As Long)

  '〇接続
  If Index = 0 Then

    '▽要求電文処理用のフォームを作成する
    Dim frmNewRecvSvrArrival As New frmRecvSvrArrival

    '▽ポートを初期化する
    frmNewRecvSvrArrival.tcpWSock.LocalPort = 0

    '▽接続要求を受け付ける
    frmNewRecvSvrArrival.tcpWSock.Accept requestID
    DoEvents

  End If

End Sub

--------------------------------
 
 ここで、frmNewRecvSvrArrivalフォームのロード(Form_Load)イベントの完了とAcceptして次の電文を受け付ける処理は必ず フォームロードイベントの完了の方が早いのでしょうか?

質問は以上です、宜しくお願い致します。


[ メッセージ編集済み 編集者: あおい 編集日時 2005-10-04 10:32 ]
たつごろー
ぬし
会議室デビュー日: 2004/10/25
投稿数: 496
投稿日時: 2005-10-04 15:42
引用:

 VB6SP5で作ったEXEが毎日似たような処理なのに2ヶ月に1回くらい、メモリアクセス違反で落ちてしまう原因を探しています。


そのプログラムだけ2ヶ月に1度おちてしまうという意味でしょうか。
メモリアクセス違反とは具体的にはどういうおちかたですか。メッセージは?
そのプログラムは起動しっぱなしで2ヶ月使うと落ちるということですか。

かなり頻繁に何度も使うFormならばグローバルスコープでいいのではないかと思います。

引用:

(一部省略あり)


再現できる最低限のコードをといいたいところですが、提示できないのは仕方がないことですしねぇ。
ですので、ここでそのものずばりの回答が出るのは期待しないで、ヒントをもらえるという程度に考えていただけるといいかと。

_________________
たつごろー
codeseek
こみゅぷらす
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2005-10-04 16:12
現状では何とも・・・まずは何処でどのように落ちているのか確認することからはじめては如何でしょう?推測が正しいことを確認しなくては、先に進めませんよね。

VB6.0で実行ファイルを作成するときに、オプションのコンパイルにある「シンボリックデバッグ情報を作成」にチェックを付けてください。続いてVC++のIDEを立ち上げ、「ファイル→開く」で作成した実行ファイルを開く。後はメニューから「ビルド→デバッグの開始→実行」後はがんばって再現させるだけです。これで大抵は原因箇所を特定できるでしょう。

#不正なメモリアクセスの結果、スタック情報などを壊している場合は無理ですが・・。

実環境でなければ再現できないと言うなら、徹底的にログを埋めてみるとか。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-10-04 16:26
こんにちは、じゃんぬ です。

引用:

あおいさんの書き込み (2005-10-04 10:24) より:

ここで、frmNewRecvSvrArrivalフォームのロード(Form_Load)イベントの完了とAcceptして次の電文を受け付ける処理は必ず フォームロードイベントの完了の方が早いのでしょうか?


制御フローを考えると Form_Load イベントの完了が先です。
本当にここが原因なんですか?

引用:

たつごろーさんの書き込み (2005-10-04 15:42) より:

かなり頻繁に何度も使うFormならばグローバルスコープでいいのではないかと思います。


そうですか?
というより頻繁に使うなら、Unload する必要がないように思えますけど。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
檸檬
ベテラン
会議室デビュー日: 2004/04/26
投稿数: 87
投稿日時: 2005-10-04 16:30
お返事ありがとうございます。まず、たつごろーさんへ回答させて頂きます。

引用:

そのプログラムだけ2ヶ月に1度おちてしまうという意味でしょうか。
メモリアクセス違反とは具体的にはどういうおちかたですか。メッセージは?
そのプログラムは起動しっぱなしで2ヶ月使うと落ちるということですか。


 そのプログラムだけ落ちます。
 メッセージは、アプリケーションエラーで「エラーが発生したため、XXX.exeを終了します。プログラムをもう一度開始する必要があります。 エラーログを作成しています。」です。
 プログラムは起動しっぱなしで1日に一度自動でリブートします。2ヶ月に一度ぐらいの頻度でそのプログラムだけ落ちます。
 また、ワトソンログが残っていましてコード「c0000005(アクセス違反)」でした。

引用:

かなり頻繁に何度も使うFormならばグローバルスコープでいいのではないかと思います。


 同時に多量の電文を受信するため処理上Newで作りました。メモリ節約の観点からも。
ただ、安定するのであればそうしたいのですが推測の原因では対策できないのが現状です。

引用:

再現できる最低限のコードをといいたいところですが、提示できないのは仕方がないことですしねぇ。
ですので、ここでそのものずばりの回答が出るのは期待しないで、ヒントをもらえるという程度に考えていただけるといいかと。


 全部で約30Kのソースでプログラムが落ちるタイミングもバラバラのため発生箇所が特定できていません。ですので、常にやっている電文受信が怪しいと考えたのですが、再現するとは限らないと思ったので、あと、一応業務のなのでそのままは載せられないのです。すいません。


[ メッセージ編集済み 編集者: あおい 編集日時 2005-10-04 16:39 ]
たつごろー
ぬし
会議室デビュー日: 2004/10/25
投稿数: 496
投稿日時: 2005-10-04 16:35
[quote]
引用:

 同時に多量の電文を受信するため処理上Newで作りました。メモリ節約の観点からも。
ただ、安定するのであればそうしたいのですが推測の原因では対策できないのが現状です。


メモリーを節約したいのでしたら頻繁にNewしてはいけません。
大量のデータを使うことがわかっているのなら、そのためのエリアをグローバルスコープで持ってはいかがでしょう。

Formに貼り付けてあるコントロールで受信処理をしているということでしょうか。

_________________
たつごろー
codeseek
こみゅぷらす
檸檬
ベテラン
会議室デビュー日: 2004/04/26
投稿数: 87
投稿日時: 2005-10-04 17:04
 甕星さんへ、デバッグでの原因追跡はぜひやってみたいとは思います。(ただ、VBしか入ってなく、開発環境だとマシンを増やしたり環境を作らないと再現しないと思うので難しそうです。)

 じゃんぬねっとさんへ、Form_Load イベントの完了が先だとすると処理が不正だとは思われないので、他の原因だと思います。

 たつごろーさんへ、Formに貼り付けてあるコントロールで受信処理をしています。グローバルスコープだと固定数の配列になりませんか?動的割り当ての方がメモリ節約になると思ったんです。あと、Form_Load イベント以降の電文受信処理などが複数電文で並行処理できるのではないかと思いました。

[ メッセージ編集済み 編集者: あおい 編集日時 2005-10-04 17:13 ]
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2005-10-04 17:44
引用:

あおいさんの書き込み (2005-10-04 17:04) より:
 たつごろーさんへ、Formに貼り付けてあるコントロールで受信処理をしています。グローバルスコープだと固定数の配列になりませんか?動的割り当ての方がメモリ節約になると思ったんです。あと、Form_Load イベント以降の電文受信処理などが複数電文で並行処理できるのではないかと思いました。


動的に確保した場合の・・・
メリット
・同時接続数は、メモリ容量の許す限り受け入れることが出来ます。

デメリット
・確保&開放を繰り返すことでヒープ領域が断片化し、連続したメモリ領域を確保できなくなる場合があります。
・何万もの同時接続を受けるとメモリ不足に陥る恐れがあります。同時接続数に上限を設けたり、空きリソースを監視し必要に応じて接続を制限したり、利用頻度の少ない接続を破棄する処理が必要になります。

固定にした場合の・・・は動的に確保した場合の正反対になるので省略

固定数で実装する場合には、Socketコントロールの配列をForm上に準備して、使いまわすことになると思います。使われていないSocketコントロールを自分で管理する必要があるので、ちょっと面倒かもしれません。

引用:

あおいさんの書き込み (2005-10-04 17:04) より:
 たつごろーさんへ、Formに貼り付けてあるコントロールで受信処理をしています。グローバルスコープだと固定数の配列になりませんか?動的割り当ての方がメモリ節約になると思ったんです。あと、Form_Load イベント以降の電文受信処理などが複数電文で並行処理できるのではないかと思いました。


所詮シングルスレッドの言語です。同時に実行されるイベントは、原則として一つだけです。DoEventsを呼ぶ方法もありますが、不用意に乱用すると、スタックオーバーフローの温床ともなるので、お勧めしません。

引用:

 同時に多量の電文を受信するため処理上Newで作りました。メモリ節約の観点からも。
ただ、安定するのであればそうしたいのですが推測の原因では対策できないのが現状です。


接続のたびにFormをNewするのは、返メモリ使用量が多くなるのではないかと。
Load tcpWSock(n)って感じで動的にコントロールを確保したほうが良いと思うよ〜。

そもそも論になっちゃうけど、TCPのサーバー側処理をVB6.0で作るのが間違いの始まりかと。通信量が多いなら、なおの事。

スキルアップ/キャリアアップ(JOB@IT)