0

現在のプログラムには大きな問題があります。ループ内で、このループ内で別の関数呼び出しを行うと、2 つの関数が永久ループになります。printf("bah");永久ループを与えることさえあります。

これにより、正常に実行されます。

//size = 10 (example)
while(size > 0) {
  a(); // decrement by 2
  b(); // decrement by 2
}

しかし

//size = 10 (example)
while(size > 0) {
a(); // decrement by 2
b(); // decrement by 2
putchar(' ');
}

永久ループを与えます。唯一の違いはputchar()呼び出しです。

何かを推測するのは難しいですが、何が起こっているのかについて何か考えはありますか?

a() andb()` 関数が基本的に行うことは次のとおりです。

配列から 2 つの構造体を取得し、そのメンバーの一部をデクリメントsizeします。このような構造は、プログラムの終了時にのみ解放されません (まだ)。1printf()

コードのこの部分をtroに投稿して、(おそらく)何が起こっているのかを理解しました。コードのこの部分から取得されたすべてのコードは非常に大きいです (ここに投稿して読んでください)。

編集:

最小限の実装を次に示しa()ますb()

void a(void) {
  foo_t* f = top;
  while(f->y == STATE_X) {
  get(&a); get(&b); /* it's equivalent to pop() in a linked list. size is size=size-1 in each get call() */
  printf("%d,%d\n",a->x,ab->x);
  f = f->next;
 }
 top = f;
}

void a(void) {
  foo_t* f = top;
  while(f->y == STATE_Y) {
  get(&a); get(&b); /* it's equivalent to pop() in a linked list. size is size=size-1 in each get call() */
  printf("%d,%d\n",a->x,ab->x);
  f = f->next;
 }
 top = f;
}

get()pop()- は、私の文脈では と同等です。

topstruct footype-スタック から最後に処理されたポイント。

size - 現在スタックにある要素の数。

struct footypeこれもリンクされているように実装されており、その前と次のメンバーを指すprevandがあります。next

4

1 に答える 1

5

表示されていないコードについてあなたが言うこと、つまりメモリが割り当てられているが解放されていないということだけを言うと、そのメモリはプログラムが終了するまで割り当てられたままになります。解放せずにさらに多くのメモリを割り当て続けると、最終的には不足し、その時点でmalloc失敗して null ポインタが返される可能性があります。(そしてもちろん、C 標準に従っている場合、null ポインターを介してメモリにアクセスしようとすると、あらゆる種類の奇抜さが発生する可能性があります。ただし、Linux で最も一般的な結果はセグメンテーション違反です。)

ただし、ulimit設定がないと、おそらくすべてのスワップ領域も使い果たし、最後に向けて大幅な速度低下を引き起こす可能性があります。そしてもちろん、プロセスでそのすべてのメモリを使用すると、他のプロセスからメモリが奪われます。最終的に、次の 2 つのいずれかが発生する可能性があります。

  • 他のプロセスがメモリの割り当てに失敗し始める可能性があります...そして、それらがそれを考慮していない場合、それらは壊れる可能性があります。

  • Linux は、意図的に架空のメモリを配布します。基本的には、RAM やスワップ領域のいずれにも支えられていないメモリ ページです。(この理由は少し複雑ですが、状況に応じて理にかなっています。) プロセスが実際にそのメモリを使用しようとする場合にのみ、カーネルは RAM を探し出します。また、RAM の空き容量がなく、スワップする余地がない場合、カーネルは既存のプロセスを強制終了して仮想メモリを再利用します。

    (そこまで行くと、どのプロセスを強制終了するかを決定するアルゴリズムがあります。一般的には、メモリに関して最悪の犯罪者であるプロセスが優先されます。この場合、おそらくあなたのものです。)

とはいえ、それは被害の程度です。あなたは物事をかなり遅くし、他のプロセスを台無しにし、おそらくそれらの1つを殺してしまいます(おそらくあなたのものです)。

少なくとも単独では実行できないことの 1 つは、ループを永久に継続させることです。それを引き起こすためには、プログラムは (1) 失敗をチェックし、(2) 操作に関連するものを何も変更せずに、失敗した操作を成功するまで再試行することを永久にループする必要があります。

ここで何か他のことが起こっています。

于 2013-05-20T22:12:45.603 に答える