プロが教えるわが家の防犯対策術!

いつもお世話になっております、While文、for文などで
無限ループが発生した場合の良い対応方法を教えて教えて
いただけないでしょうか? 最小限で且つ最速な変更が
一番助かります。
-------------------------------------------------------
【例】
for(;;){
if(iNum == 10) break;
}
この場合だと、iNumが10になるまで抜けない為
無限ループになりPCがフリーズしてしまいます。
-------------------------------------------------------
【対応】
【例】
for(;;){
if(iNum == 10) break;
delay(1);
}
一番簡単な対応だと、delay1を入れる事により
PCのフリーズが防げると思います。ですが、delay1を入れる
事により処理が重くなってしまいます。
-------------------------------------------------------
そこで教えていただきたいのは、PCがフリーズさせない
ような処理は他にないでしょうか?

そのような関数が100ほどあるので、出来るだけ最小限な
改造で薦めたいと思っています。

以上です。

A 回答 (10件)

UNIXについては全く詳しくありませんが・・・


無限ループ内で一定ループや一定時間ごとにCPU使用率を調べ、一定以上になっていたらdelayする、みたいなのは駄目でしょうか?
具体的にはループ内で一定ごとに/proc/loadavgでcpuの利用率を得て何とかする、みたいな感じでいけないかと。/proc/
↓Linuxでの/procの解説ページですが、参考までに。
http://www.atmarkit.co.jp/flinux/special/proctun …

検索かけて回答しただけなので、自分でも良く分かっていません。ちんぷんかんぷんな事を言っていたら無視してください。
    • good
    • 0

> QNX Software Systemsと言ったリアルタイムOS(UNIX系)を


> 使っており。 開発言語はC言語です。

そのRTOSを使ったことは無いのですが、マルチスレッドのプログラムを書く場合、一般的にはこんな風に書きます。
-------------------------------
(イベントフラグを使った例)
while(1){
 wait_event( event_flag ); // OSが提供する同期通信機能
 switch( event_flag ){
 case EVENT_A:
 (省略)
 }
}
-------------------------------
同期通信機能には、
- イベントフラグ
- セマフォ(ロック、ミューテックスとも言う)
- メールボックス
- データキュー
等々があり、用途に応じて使い分けます。

おそらく、QNXの仕様書をみれば使用可能な同期通信機能に関する記載があると思いますので、それを使ってみてはいかがでしょうか。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

新規で開発する場合は、メッセージキュー(プロセス間通信)など
を使用して、同期など取っているのですが、今回は予算も少なく、
他会社が捨てたプログラムの修正ですので、どうしても大幅な改造が
出来ない状態です。

根本的な所からソフトを作りたい所ですが、現状のソフトが
フリーズする現象だけでも直す依頼ですので、つらい所が
あります。

今後のプログラムを作成する上で色々と参考にさせて
いただきます、ありがとうございました。

お礼日時:2009/12/17 17:47

C/C++は言語使用レベルでマルチスレッド/マルチタスクをサポートしていません。

なので、こういった話はOSによって対処が違います。
delayという関数も標準の関数ではありませんしね。

気長に「QNX Software Systems」を使っている人が現れるのを待つよりは、メーカーのサポートに問い合わせたほうが早そうです。

http://www.qnx.co.jp/

フォーラムもあるみたいですよ。
http://community.qnx.com/sf/projects/qnx-j-commu …
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

色々な、情報ありがとございます。
是非とも参考にさせていただきます。

お礼日時:2009/12/17 17:18

ループの中にdoEventsを入れるのはどうですか?


http://homepage2.nifty.com/kasayan/vba/doevents. …
http://oshiete1.goo.ne.jp/qa2008316.html
ただし、これは昔のWin95や98の擬似マルチタスクだった頃に有効だった手段ですが。
今のXPなどは完全なマルチタスクなので無意味かもしれません。
    • good
    • 0
この回答へのお礼

回答ありがとうございます、環境の説明不足でした。

QNX Software Systemsと言ったリアルタイムOS(UNIX系)を
使っており。 開発言語はC言語です。

お礼日時:2009/12/17 17:16

共通のサブルーチンを1つ作って、そのサブルーチンが一定回数呼ばれるごとにdelayするんじゃだめですかね?


色んなスレッドから呼ばれる場合は、スレッドごとに回数カウンタをパラメータで渡してやらないとまずいとは思いますけど。
    • good
    • 0
この回答へのお礼

回答ありがとうございます、私もその案を考えていました。

そのサブルーチンが一定回数呼ばれるごとにdelayを行い
フリーズを防止する、その後ログを残すって言う感じです。

しかし、zwiさんもおっしゃる通り色んなスレッドから呼ばれる
状態で困っています。 しかもそのスレッドがサブルーチン
だったりするから困り物です。 プロセスID、引数など・・・etc

検討しています。 ありがとうございました。

お礼日時:2009/12/17 17:11

実行タイミング制御が適切に行われていないように見えるので、「処理が重くなる」の判断基準については、よくわかりません。


メインの処理を見ると、ループ変数の値で処理フラグが制御されているので、処理がいつ始まって、いつ終わってもおかしくないと思います。

無限ループにdelayを入れたとしても、フリーズは回避されないかもしれませんね。
例えば、メインの処理だけが動き続けてiNum=20にしてしまい、サブのスレッドは全く動けず、iNum=10を期待して待ち続けて、その結果、無限ループに陥っているのかもしれません。
いずれにせよ、なぜフリーズするのか、状況を把握することは、必要でしょう。
組み直すのが一番早く、確実な解決方法だという結論になるかもしれませんが。
    • good
    • 0
この回答へのお礼

回答ありがとうございます、説明不足でした申し訳ありません。
処理が重くなるというより、処理に時間が掛かるの間違いです。

メインプログラムでもループしており、同じ用にdelay(1)を
入れようと思っています。この場合メインの処理が遅くなる為
SubAから処理が抜けるには、少なくても1000msec時間が
掛かると思います。 あくまで例ですので実際のプログラムは
5秒かもしれないし、10秒かも・・・出来るだけそれを避けたい
ので思案中です。

// サブルーチンA(データ収集用)
void SubA(){
for(iCnt=0;;iCnt++){
iBuf1[iCnt]=iCnt; // iBufにiCntの数を入れていく
if(iNum == 10) break; // iNumに10が入ったら抜ける
delay(1); // ←ここに追加
}

// サブルーチンB
void SubB(){
for(;;){
SubA();
iBuf2=iBuf1;
if(iNum == 20) break; // iNumに20が入ったら抜ける
delay(1); // ←ここに追加
}

// メイン(別プログラム)
Main(){
for(iCnt=0;;iCnt++){
if(iCnt == 1000)iNum = 10;
if(iCnt == 2000)iNum = 20;
delay(1); // ←ここに追加
}
}

お礼日時:2009/12/17 17:04

明確には書かれていませんがWindowsであって、問題の関数がCWnd派生クラスのメンバであれば、ループ中に以下の処理をすることによって、Windowsの操作が行える。


// ここから
if (PeekMessage (&msg,NULL,0,0,PM_NOREMOVE)) {
if (!GetMessage (&msg,NULL,0,0)) return;
TranslateMessage(&msg);
DispatchMessage(&msg);
   }
// ここまで
ただし問題の関数の実行は遅くなります。 
詳しくは"メッセージループ"で検索するか、上記の関数名で検索してください。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

環境の説明不足でした。
QNX Software Systemsと言ったリアルタイムOS(UNIX系)を
使っており。 Wisdowsの操作は使えない状態です。

お礼日時:2009/12/17 15:35

無限ループしたら、「ctrl + c」で強制終了させるとか。

    • good
    • 0
この回答へのお礼

回答ありがとうございます。

無限ループになってしまったらOS自体がフリーズしてしまう為
CTRL+Cも使えない状態になってしまっています。

お礼日時:2009/12/17 15:28

アプリ自身の優先度を下げれば、ビジーループ中でも他のアプリを阻害することはなくなります。


優先度が落ちるのでアプリの実行時間もそれだけ長くはなりますが。

もちろん最良なのは、言うまでもないとは思いますがそんな作りを根本から見直すことです。
どうやらマルチスレッドプログラムのようですから、スレッド待ち合わせ機構を使うとか。
    • good
    • 0
この回答へのお礼

回答ありがとうございます、アプリの優先順位を下げる方法は
以前おこなってみましたが、それでもPCがフリーズする現象に
なってしまっていました。 どのプログラムよりも優先順位を
下げても同じ状態でした。

>もちろん最良なのは、言うまでもないとは思いますがそんな作りを
>根本から見直すことです。
確かに根本的に作り直すのが望ましいのですが、低予算となると
現状大改造が出来ないのが現状です。社内で作成するプログラムでは
スレッド待ち合わせ機構を使用しているのですが、他会社が
投げ捨てたソフトを改造するような状態ですのでどうしても
作り直しがつらい状況にあります。 出来るだけ最小限の包帯で
対応って感じです。 

お礼日時:2009/12/17 15:04

ループ回数でbreakするとか、clock()で一定時間経過したら抜けるなど、


いくつか方法はあると思いますが、普通は、無限ループが発生させないようにすることに注力します。
なぜ無限ループが必要なのか、どういう処理を行いたいのかを補足してもらえると回答がつきやすいと思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

大まかな状態なのですが下記のような状態です。
-----------------------------------------------------
// サブルーチンA(データ収集用)
void SubA(){
for(iCnt=0;;iCnt++){
iBuf1[iCnt]=iCnt; // iBufにiCntの数を入れていく
if(iNum == 10) break; // iNumに10が入ったら抜ける
}

// サブルーチンB
void SubB(){
for(;;){
SubA();
iBuf2=iBuf1;
if(iNum == 20) break; // iNumに20が入ったら抜ける
}

// メイン(別プログラム)
Main(){
for(iCnt=0;;iCnt++){
if(iCnt == 1000)iNum = 10;
if(iCnt == 2000)iNum = 20;
}
}

あくまで例ですが、このような感じでfor文やWhile文が
入り組んだ状態になっており、どこでフリーズしたんだろう?
それを直すにはdelayを入れるのが手っ取り早いかな。
と言う次第であります。

お礼日時:2009/12/17 15:25

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!