- PR -

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

投稿者投稿内容
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2005-10-04 17:52
引用:

 グローバルスコープだと固定数の配列になりませんか?動的割り当ての方がメモリ節約になると思ったんです。


スコープと動的静的は関係ないはずよね。
Public objSock() As WinSock
と書けばよいわけですので。
節約ならじゃんぬねっとさんの言われるようにコントロールのインスタンスを再利用したり
あとはフォームを使用しないとか。(フォーム自体がメモリを食いますから)

気になるのは、例のプロシージャ内でローカルでNewしていることと、
それをどこでNothingにしてるんだろうかということ。。。
たつごろー
ぬし
会議室デビュー日: 2004/10/25
投稿数: 496
投稿日時: 2005-10-04 18:02
オブジェクトを新規生成することでメモリー効率が悪くなるなら
「フライウェイトパターン」が解決策になる可能性があります。

http://www.google.co.jp/search?hl=ja&q=%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3+%E3%83%95%E3%83%A9%E3%82%A4%E3%82%A6%E3%82%A7%E3%82%A4%E3%83%88&lr=

さらにこのクラス内でもメモリーを動的に取得するのを出来るだけ減らします。
VB6の場合Formもクラスと同様の挙動になります。

_________________
たつごろー
codeseek
こみゅぷらす
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2005-10-04 18:24
こんにちは。

怪しいと思われる箇所の前後にテキストファイルにログを吐き出す処理を書けばどうでしょうか?

日時や、ステートメントの箇所(モジュール名.サブルーチン名)、変数などの値など
を記録していきます。
どこまで処理が進みどの箇所で落ちたかが分かるようになります。
※分かるようなログの吐き出し方にすれば

出力されるログのサイズには気をつけてください。
檸檬
ベテラン
会議室デビュー日: 2004/04/26
投稿数: 87
投稿日時: 2005-10-05 10:26
 たくさんのお返事ありがとうございます。
 このプログラムをつくった当初は、VBの仕様自体手探り状態(今も似たようなものですが)だったので、その頃の話になってしまいます。
 まず、DoEventsをたくさん使わずに同時多数受信する電文を同時に処理するには別フォームにするしかないと思いました。あと、1電文4Kバイトある電文を受信バッファに溜めすぎるのはよくないと思ったんです。
 ログを見ると同時処理数は多くて2つ(電文はもっと多いはずです。)なのでこの方法で並行処理できているか怪しいと思います。ですので、いまから考えると固定配列のコントロール(フライウェイトもいいと思います)で別フォームにせずに実装した方が安定するんだと思います。ただ、それでも一応動いているので推測の原因でそこまで変えられない状態です。
 そもそもVBで作るのが間違いだとういのは賛成ですね。同時処理もそうですが、受信したバイト配列の処理が大変でした。そもそもVCを買ってなかったので無理やり作ったんですが。

 プロシージャ内でローカルでNewしているフォームですが、どこでもNothingにしていません。1つの電文を処理したら自分でアンロードするようにしています。
 ログ出力をソースに組み込む件ですが、プログラムが落ちるタイミングが特定できていないので、プログラム全体を疑ってもいいですが、それでエラー発生しても箇所が特定できるとは思えない(可能性が低いとういだけですが、そういう理由で簡単にソースをいじれませんし量でもないので)ので恐らくやらないと思います。今はソース全体を眺めています


[ メッセージ編集済み 編集者: あおい 編集日時 2005-10-05 11:26 ]
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2005-10-05 14:34
引用:

 まず、DoEventsをたくさん使わずに同時多数受信する電文を同時に処理するには別フォームにするしかないと思いました。あと、1電文4Kバイトある電文を受信バッファに溜めすぎるのはよくないと思ったんです。
 ログを見ると同時処理数は多くて2つ(電文はもっと多いはずです。)なのでこの方法で並行処理できているか怪しいと思います。


DoEventsは溜まっている「WindowsOSのメッセージ」を処理するものですので
あまり関係ないような気がします。
VB6だと同一スレッド上で動くはずなので、つまりプロシージャの単位で同期に実行されてますので
同時には動いていないはずです。(よね?)
檸檬
ベテラン
会議室デビュー日: 2004/04/26
投稿数: 87
投稿日時: 2005-10-05 14:57
当時はそれで同時に動くと思っていました。画面が別だと1つの画面が処理中でも別の画面はとりあえず入力は受け付けますよね。それで、そう思ったんだと思います。

同時に動かないのではこうした意味もないわけで、設計ミスだったとゆうことになります。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-10-05 14:58
こんにちは、じゃんぬ です。

引用:

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

まず、DoEventsをたくさん使わずに同時多数受信する電文を同時に処理するには別フォームにするしかないと思いました。
あと、1電文4Kバイトある電文を受信バッファに溜めすぎるのはよくないと思ったんです。


今はそうは思っていないと読み取れたのでスルーします。

引用:

プロシージャ内でローカルでNewしているフォームですが、どこでもNothingにしていません。
1つの電文を処理したら自分でアンロードするようにしています。


Unload しているなら大丈夫でしょう。
参照カウンタは、Nothing で参照を解放しなくともスコープを抜ければ減少するはず。
また別のオブジェクトのインスタンスを格納しても減少します。
特に Nothing を入れないからといって、残ってしまうことはないです。

# あんまり VB 詳しくない...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
葉瀬崎浩樹
大ベテラン
会議室デビュー日: 2005/06/28
投稿数: 115
お住まい・勤務地: 兵庫県
投稿日時: 2005-10-05 15:12
こんにちは。
引用:

まどかさんの書き込み (2005-10-05 14:34) より:
DoEventsは溜まっている「WindowsOSのメッセージ」を処理するものですので
あまり関係ないような気がします。
VB6だと同一スレッド上で動くはずなので、つまりプロシージャの単位で同期に実行されてますので同時には動いていないはずです。(よね?)


ここだけ反応。VB6で確認してみました。
Form1とForm2を作成し、それぞれのフォームにCommandButtonを1つ配置しました。
コード:
'Form1.frm
Private Sub Command1_Click()
    Dim f2 As New Form2
    f2.Show
End Sub

'Form2.frm
Private Sub Command1_Click()
    Dim counter As Long
    For counter = 0 To 30000
        Command1.Caption = counter
        DoEvents
    Next
End Sub


Form2が複数起動していても、それぞれのCommand1_Click処理は同期を取っていますね。
#勿論、同一フォーム内でボタン連打時は、イベントの再入が発生しますけど。

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