Gdbのデバッグ情報とデバッグの原則

    LinuxでのC ++プログラム開発では、makefileやcmakeなどのコンパイルツールが使用されている場合でも、コンパイラツールグループgccが最終的に呼び出されますここで説明するツールセットは、CプログラムとC ++プログラムのコンパイルに使用されるコンパイラツールにまだ少し違いがあるためです。通常gccCプログラムのコンパイルに使用され g ++はC ++プログラムのコンパイルに使用されます (以下の説明の便宜上、特に明記されていない限り、gccとg ++は特に区別されておらず、gccという用語は一律に使用されています。)

このコースで使用するオペレーティングシステムはCentOS7.0です。これは、デモンストレーションの便宜のためにルートアカウントのデモンストレーションです。gccとgdbがリーダーのマシンにインストールされていない場合は、yum コマンドを使用して それらをインストールできます。

# 安装 gcc
yum install gcc
# 安装 g++
yum install gcc-c++
# 安装 gdb
yum install gdb

コピー

通常、プログラムをデバッグする必要があります。スタック情報、変数名、関数名など、デバッグ中のコードの各行の情報を明確に確認するには、デバッガーにデバッグシンボル情報を含める必要がありますgccを使用 てプログラムコンパイルするときに -g オプションを追加する と、デバッグシンボル情報をコンパイル済みプログラムに保持できます。たとえば、次のコマンドは、デバッグ情報を含むプログラムhello_serverを生成します。

gcc -g -o hello_server hello_server.c

コピー

では、hello_serverにデバッグ情報が含まれているかどうかを判断するにはどうすればよいでしょうか。gdbを使用してこのプログラムをデバッグします。gdbは正しく読み取られたプログラムのデバッグ情報を 表示します。開いているLinuxシェルターミナルにgdbhello_serverと入力し て、表示された結果を表示します。

[root@localhost testclient]# gdb hello_server
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7_4.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/testclient/hello_server...done.
(gdb)

コピー

gdbが正常にロードされると、次の情報が表示されます。

Reading symbols from /root/testclient/hello_server...done.

コピー

つまり、シンボルファイルの読み取りが完了すると、プログラムにデバッグ情報が含まれていることを示します。-g オプションを指定せずに再試行してみましょう 

[root@localhost testclient]# gcc -o hello_server2 hello_server.c
[root@localhost testclient]# gdb hello_server2
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7_4.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/testclient/hello_server2...(no debugging symbols found)...done.
(gdb)

コピー

注意深い読者は違いを 理解する必要があります.gdbを使用して-gオプションなしで hello_server2プログラムをデバッグおよび生成すると、デバッグシンボル情報を読み取るときに次のプロンプトが表示されます。

Reading symbols from /root/testclient/hello_server2...(no debugging symbols found)...done.

コピー

ちなみに、-gオプションを追加しないことに加えて、Linuxのstripコマンドを使用して、プログラムのデバッグ情報を削除することもできます。hello_serverでstripコマンドを試してみましょう。

[root@localhost testclient]# strip hello_server
##使用 strip 命令之前
-rwxr-xr-x. 1 root root 12416 Sep 8 09:45 hello_server
##使用 strip 命令之后
-rwxr-xr-x. 1 root root 6312 Sep 8 09:55 hello_server

コピー

hello_serverでstripコマンドを使用した後、プログラムが大幅に小さくなっていることがわかります(12416バイトから6312バイトに減少)。通常、プログラムをテストした後、本番環境または正式な環境に問題なくリリースするため、プログラムのサイズを縮小したり、プログラムの実行効率を向上させたりするために、シンボル情報をデバッグしないプログラムが生成されます。

gdbを使用して、このプログラムのデバッグ情報が実際に削除されていることを確認しましょう。

[root@localhost testclient]# gdb hello_server
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7_4.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/testclient/hello_server...(no debugging symbols found)...done.
(gdb)

コピー

2つの追加の説明:

  • このコースでは例としてgccを使用していますが、-gオプションは、実際にはmakefileやcmakeなどのツールでコンパイルされたLinuxプログラムにも適用できます。
  • 実際にデバッガーを生成する場合は、通常、-gオプションを追加するだけでなく、コンパイラーのプログラム最適化オプションをオフにすることをお勧めします。コンパイラのプログラム最適化オプションには、通常、O0からO4までの5つのレベルがあり(最初のO0は文字Oと数字の0であることに注意してください)、O0は最適化なしを意味し、O1からO4までは最適化レベルがどんどん高くなっています。最高です。これの目的はデバッグのためであり、シンボルファイルに表示されるデバッグ変数は完全にソースコードに対応することができます。たとえば、次のコードがあるとします。
  int func()
  {
      int a = 1;
      int b = a + 1;
      int c = a + b;
      return a + b + c;
  }

  int main()
  {
      int a = func();
      printf("%d\n", a);
  }

コピー

このコードでは、func()関数がmain()関数で呼び出されるため、コンパイル中にfunc()関数の値を直接計算できます。最適化オプションをオンにすると、この関数のローカル変数は実際にはデバッグ済み。a、b、cは直接値に置き換えられます(つまり、コンパイラによって計算された値は、aが1を直接使用し、bが2を直接使用し、cが3を直接使用します。これにより、aおよびcによる計算bは生成されません。 c by aおよびb命令)、関数func()でさえ最適化することができます。この場合、デバッガーが表示するコードと実際のコードが異なる場合があり、トラブルシューティングが困難になります。もちろん、上記の最適化現象が確実に発生するかどうかにかかわらず、コンパイラのバージョンが異なれば、動作も異なる可能性があります。つまり、デバッグファイルを生成するときは、コンパイラの最適化オプションをオフにすることをお勧めします

概要

このレッスンでは、主にgdbなどのツールのインストールと、デバッグ用のデバッグシンボルの重要性を紹介します。同時に、コンパイラの最適化オプションがデバッグの正確さに与える影響にも注意を払う必要があります。

おすすめ

転載: blog.csdn.net/weixin_38293850/article/details/107974741