0

**A別のポインター ( ) へのポインター ( ) があり*Bます。プログラムのどこかBが壊れています。ただし、 に格納するBに破損しています。は常に同じアドレスにあるとは限りません (は必ずしも同じではありません)。しかし、B は常に同じ値で破損しています (は常に同じです)。に格納される次の値を調べる破損検出ルーチンがあるため、これを知っています。そのため、既に破損している時点しかわかりません。*AB&BB*A

私が (もちろん) 望んでいるのBは、破損している場所を見つけることです。

( ) を指すAものにウォッチポイントを自動的に生成するgdbウォッチポイントを既に試しました. .A*AB*A*A*A

watch A
commands
  silent
  watch *A
  commands
    silent
    if *A == magicalcorruptedvalue
      where
    end
  end
end

しかし問題は、ハードウェア ウォッチポイントを使用すると、あまりにも多くの中間的なものが に保存される*Aため、すぐにウォッチポイントが不足してしまうことです。スレッドではうまく機能しないため、ソフトウェア ウォッチポイントは試していません。

この時点で、唯一の解決策は、戻ってコードをより注意深く読むか (常にまともなオプションです)、より多くの単体テストを作成するか、割り当てられたすべてのメモリを継続的にスキャンしてこの値を探し続ける専用スレッドを作成することです。 .

ただし、この問題に遭遇したのは私が初めてではないと思います。この質問をより一般的に表現すると、次のようになります。

メタパラメータ:

  • Linux の場合

  • これは、マルチスレッド コールバック スタイルのアプリケーションにあります。

4

1 に答える 1

0

私は2つの答えを思いつきました。そのうちの1つは実際にうまくいきました。

  1. 仕事に適したツールを使用してください。gdb は、プログラム フローのデバッグ用です。valgrindは、メモリ/バッファ エラーのデバッグに適しているようです。valgrind でプログラムを実行すると、バグがすぐに見つかりました。

  2. 実際には、理論的には gdb でこれを行う方法があります。*A実際には、比較的めったに変更されない場合にのみ、十分に高速になります。この特定のプログラムで変更された 10,000 回以上ではありません。

ここにあります:

set $A = (void ***) &whateveritis
set $B = (void **) 0
set $WPN = 2
set $WP = 0
watch *$A
commands
  silent
  set $B = *$A
  if $WP != 0
    delete $WP
    set $WP = 0
  end
  if $B != (void *) 0
    watch *$B
    commands
      silent
      if *$B == magicalcorruptedvalue
        where
      else
        continue
      end
    end
    set $WP = $WPN++
  end
  continue
end

これは にウォッチポイントを設定しA、前の に存在していた以前のウォッチをすべて削除し*A(最終的には に設定されますB)、現在の にウォッチを設定し*Aます。時計は常にmagicalcorruptedvalueを探していますが、私の場合、B保存中に変更があった場合*Aはエラーになるため、その部分全体を省略しました.

$WPN は次のブレークポイントの番号であることに注意してください。によって作成されたような一時的な暗黙的なブレークポイントによる変更に注意してくださいstart

これは機能するはずですが、私の場合、プログラムが行き詰まりすぎて破損したセクションに到達しなかったため、のウォッチポイントBがトリップしなかったことに注意してください。YMMV。

gdb でこれほど複雑なことを行う人が誰もいない現実の世界に戻りましょう。ここでの教訓は次のとおりです。 (1) そこにあるツールを学びます。Valgrind は驚くべきものであり、C プログラマーが Valgrind なしでどのように対処したかは、私も含めてまったくわかりません。(2) 問題のドメインと、使用しようとしているツールとの関係について慎重に考えてください。ツールが適合しない場合は、別のものを使用するか、記述してください。言語にだまされてはいけません。「デバッグ」しているからといって、「デバッガ」を使用して実行する必要があるわけではありません。

于 2013-09-21T09:09:54.160 に答える