LinuxデバッガGDBの基本的な使い方の詳細な説明

LinuxデバッガGDBの基本的な使い方の詳細な説明

1. 概要

GDB デバッグの 3 つの方法:

1. ターゲットボードは GDB を使用して直接デバッグされます。

2. ターゲット ボードは gdbserver を使用し、ホストはクライアントとして xxx-linux-gdb を使用します。

3. ターゲット ボードは ulimit -c unlimited を使用してコア ファイルを生成し、次にホストは xxx-linux-gdb ./test ./core を使用します。

2. gdbデバッグ

次のように main.c と sum.c でテスト プログラムを構築します。

main.c: #include <stdio.h>
#include <stdlib.h>
 
外部 int 合計(int 値);
 
構造体入出力{
    int 値;
    int 結果;
};

int main(int argc, char * argv[])
{
    構造体 inout * io = (構造体 inout * ) malloc(sizeof(構造体 inout));
    (NULL == io)の場合{
        printf("Malloc に失敗しました。\n");
        -1 を返します。
    }

    (引数が2の場合){
        printf("間違ったパラグラフです!\n");
        -1 を返します。
    }

    io->値 = *argv[1] - '0';
    io->結果 = sum(io->値);
    printf("入力: %d、結果: %d\n", io->value, io->result);
    0を返します。
}
合計.c:
int 合計(int 値) {
    int 結果 = 0;
    整数 i = 0;
    (i = 0; i < 値; i++) の場合
        結果 += (i + 1);
    結果を返します。
}

次に、gcc main.c sum.c -o main -g を実行して、メインの実行可能ファイルを取得します。

以下ではgdbのほとんどの機能を紹介します。1.1 ブレークポイントの設定と1.3 スタックフレームの表示はよく使われる機能です。デバッグ中には、1.6 シングルステップ実行、1.4 変数の表示、1.5 レジスタの表示、1.8 ウォッチポイント、および1.9 変数値の変更が必要になる場合があります。

プロセスがすでに実行されている場合は、1.11 でプロセスにアタッチするか、1.10 で分析用のダンプ ファイルを生成する必要があります。もちろん、効率を向上させるために、1.13 初期化ファイルをカスタマイズすることもできます。

2.1. ブレークポイントを設定する

b または break を使用してブレークポイントを設定できます。ブレークポイントは、関数名、行番号、ファイル名 + 関数名、ファイル名 + 行番号、オフセット、アドレスなどで設定できます。

形式は次のとおりです。

ブレーク関数名

改行番号

ブレークファイル名: 関数名

ファイル名:行番号を区切る

ブレーク + オフセット

ブレーク - オフセット

ブレーク *アドレス

ブレークポイントを確認し、info break を通じてブレークポイント リストを表示します。

コマンドによるブレークポイントの削除には次のものがあります:

delete <ブレークポイントID>: 指定されたブレークポイントを削除します

削除: すべてのブレークポイントを削除します

クリア

関数名をクリアする

クリアライン番号

ファイル名:行番号をクリア

クリアファイル名: 関数名

ブレークポイントは条件付きで解除することもできる

break breakpoint if condition; たとえば、break sum if value==9 の場合、入力値が 9 の場合にのみ実行が停止します。

条件ブレークポイント番号: 指定されたブレークポイントのトリガー条件を削除します

条件ブレークポイント番号条件: 指定されたブレークポイントにトリガー条件を追加します

下記のように、入力パラメータが 9 の場合は中断され、入力パラメータが 8 の場合は最後まで実行されます。

ブレークポイントは、disable/enable を使用して一時的に無効または有効にすることもできます。

無効にする

ブレークポイント番号を無効にする

表示を無効にする 番号を表示する

memメモリ領域を無効にする

有効にする

ブレークポイント番号を有効にする

ブレークポイント番号を 1 回有効にする: このブレークポイントは 1 回だけ有効になります。プログラムがこのブレークポイントまで実行されて一時停止すると、ブレークポイントは無効になります。

ブレークポイント番号の削除を有効にする

表示を有効にする 表示番号

メモリ領域を有効にする

2.1.1. ブレークポイントコマンドの高度な機能

ほとんどの場合、ブレークポイントで一連のアクションを実行する必要があります。gdb は、ブレークポイントでコマンドを実行するためのコマンドと呼ばれる高度な機能を提供します。

#include <stdio.h>

整数合計 = 0;

整数平方(整数i)
{
    結果=0;

    結果 = i*i;

    結果を返します。
}

int main(int argc, char **argv)
{
    整数 i;

    (i=0; i<10; i++) の場合
    {
        合計 += 平方(i);
    }
    0を返します。
}

たとえば、上記のプログラムで square パラメータ i が 5 のときにブレークポイントを設定し、この時点でのスタック、ローカル変数、合計の値を印刷する必要があります。

gdb.init を次のように記述します。

gdb.log にログを設定する


i == 5 の場合、b の平方
コマンド
  btフル
  地元の人々
  p合計
  「i == 5 のときにブレークする」と出力します。
終わり

gdb シェルで、gdb.init をソースとして実行し、コマンド r を実行します。結果は次のようになります。

i==5 のときにブレークポイントが解除され、この時点で正しい値が出力されることがわかります。

2.2. 操作

「gdb コマンド」の後に run を実行すると、gdb でコマンドを実行できます。コマンドにパラメータが必要な場合は、run にパラメータが続きます。

main() にブレークポイントが必要な場合は、start を直接実行してください。

2.3. スタックフレームを表示する

ブレークポイントに到達すると、実行が一時停止され、または coredump によってスタック フレームが表示されることがあります。

bt はスタック フレームを表示でき、bt full はローカル変数を表示できます。

コマンドの形式は次のとおりです。

ビット

bt full: バックトレースだけでなく、ローカル変数も表示します

bt N: 最初のN個のスタックフレームを表示する

btフルN

2.4. 変数の表示

「print variable」は変数の内容を表示できます。

1 行で複数の変数を監視する必要がある場合は、p {var1, var2, var3} を使用できます。

自動表示を追跡したい場合は、display {var1, var2, var3}を使用できます。

2.5. ディスプレイレジスタ

info reg はレジスタの内容を表示できます。

レジスタの内容を表示するには、レジスタ名の前に $ を追加します。

p $register: レジスタの内容を表示する

p/x $register: レジスタの内容を16進数で表示します。

x コマンドを使用して、内容「x/format address」を表示します。

x $pc: プログラムポインタの内容を表示する

x/i $pc: プログラムポインタアセンブリを表示します。

x/10i $pc: プログラムポインターの後の 10 個の命令を表示します。

x/128wx 0xfc207000: 0xfc20700 から始まる 16 進数で 128 語を出力します。

disassemble コマンドを使用して逆アセンブルすることもできます。

分解する

プログラムカウンターを逆アセンブルします。pc が配置されている関数全体を逆アセンブルします。

disassemble addr-0x40,addr+0x40: 前後に 0x40 がある addr を逆アセンブルします。

2.6. シングルステップ実行

シングルステップ実行には、next と step の 2 つのコマンドがあります。この 2 つの違いは、next は関数に遭遇してもその関数に入らないのに対し、step は関数内で実行されることです。

アセンブリ命令を 1 つずつ実行する必要がある場合は、それぞれ nexti と stepi を使用できます。

2.7. 実行を継続する

デバッグ時は、continue コマンドを使用してプログラムの実行を続行します。停電後、プログラムは再び一時停止します。ブレークポイントがない場合、最後まで実行を続けます。

続行: 実行を続行する

継続回数: 指定回数実行を継続します。

2.8. 監視ポイント

変数がどこで変更されたかを確認するには、watch コマンドを使用してウォッチポイントを設定します。

<式> を見る: 式が変わったら一時停止する

awatch<expression>: 式にアクセスし、変更を一時停止します

rwatch<式>: 式にアクセスしたときに実行を一時停止する

その他のバリエーションには、watch expr [thread thread-id] [mask maskvalue] などがあります。ここで、mask にはアーキテクチャ サポートが必要です。

GDB は定数を監視できません。たとえば、watch 0x600850 はエラーを報告します。

ただし、*(int *)0x600850 は監視できます。

2.9. 変数の値を変更する

「set variable <variable>=<expression>」で変数の値を変更します。

set $r0=xxx: レジスタ r0 の値を xxx に設定します。

2.10. カーネルダンプファイルを生成する

「generate-core-file」を使用して core.xxxx ダンプ ファイルを生成します。

次に、gdb ./main ./core.xxxx を使用して、復元されたシーンを表示します。

別のコマンド gcore を使用すると、コマンド ラインから直接コア ダンプ ファイルを生成できます。

gcore `pidof コマンド`: 実行中のプログラムを停止せずにダンプ ファイルを取得します。

2.11. プロセスにアタッチする

プログラムがすでに実行中の場合、またはデバッグが無限ループに陥ってコンソール プロセスに戻れない場合は、attach コマンドを使用できます。

pidを添付する

ps aux を使用してプロセスの pid を表示し、bt を使用してスタック フレームを表示できます。

top を例にとると、操作手順は次のようになります。

1. ps -aux を実行してプロセス pid (16974) を表示します。

2. sudo gdb attach 16974 を実行し、gdb を使用して top コマンドにアタッチします。

3. bt full を使用して現在のスタック フレームを表示します。このとき、印刷などを利用して情報を閲覧してください。

4. info proc を使用してプロセス情報を表示することもできます。

2.12. 繰り返し実行

continue、step、stepi、next、nexti はすべて繰り返し実行の回数を指定できます。

ブレークポイントを指定した回数無視: 指定した数のブレークポイントを無視できます。

2.13. 初期化ファイル

Linux 環境での初期化ファイルは .gdbinit です。

.gdbinit ファイルが存在する場合、gdb は起動前にそれをコマンド ファイルとして実行します。

初期化ファイルとコマンド ファイルの実行順序は、HOME/.gdbinit > コマンドライン オプションの実行 > ./.gdbinit > -x でコマンド ファイルを指定します。

2.14. ソースディレクトリを設定する

デバッグ中にソースコードに関連付ける必要がある場合は、より詳細な情報を表示します。

ソース ディレクトリは、directory または set substitute-path で指定できます。

2.15 TUIデバッグ

TUI (TextUserInterface) は、GDB デバッグ用のテキスト ユーザー インターフェイスであり、ソース コード、アセンブリ、レジスタ テキスト ウィンドウを便利に表示できます。

ソース コード ウィンドウとアセンブリ ウィンドウでは、プログラムの実行場所が強調表示され、「>」記号でマークされます。ブレークポイントを識別するために使用される特別なタグが 2 つあります。最初のタグはブレークポイントの種類を識別します。

  • B:プログラムは少なくとも 1 回このブレークポイントに到達しました。
  • b:プログラムはこのブレークポイントまで実行されていません
  • H:プログラムはこのハードウェア ブレークポイントに少なくとも 1 回到達しました。
  • h:プログラムはこのハードウェアブレークポイントまで実行されていません

2 番目のフラグは、ブレークポイントが有効かどうかを示すために使用されます。

+:ブレークポイントが有効です。- -:ブレークポイントが無効です。

プログラムをデバッグすると、ソース コード ウィンドウ、アセンブリ ウィンドウ、レジスタ ウィンドウの内容が自動的に更新されます。

2.16 キャッチポイント

Catch は、特定の種類のイベントに基づいてプログラムの実行を停止できます。

システム コール close が生成されたときにプログラムの実行を停止するには、catch syscall close を使用できます。

その他のキャッチ イベントには、throw、syscall、assert、exception などがあります。

2.17 カスタムスクリプト

コマンドラインの入力パラメータは、argc および *argv を通じて取得できます。

2.17.0、注釈、割り当て、表示

# - スクリプトにコメントを追加します。

set - gdb 変数とデバッガー変数を区別するために $ で始まる変数に値を割り当てます。

例えば: $x = 1 と設定する

変数の表示は echo と printf を通じて行うことができます。

2.17.1 カスタムコマンド

define コマンドを使用して独自のコマンドを定義したり、document コマンドを使用してカスタム コマンドに説明を追加したりすることもできます。

加算器を定義する
  $argc == 2の場合
    $arg0 + $arg1 を印刷する
  終わり
  $argc == 3の場合
    $arg0 + $arg1 + $arg2 を印刷します
  終わり
終わり

ドキュメント追加
  2 つまたは 3 つの変数を合計します。
終わり

bfカスタムコマンドを実行すると、結果は次のようになります。

行パラメータ宣言はありませんが、$arg0、$arg1、$argcを使用して直接参照できます。$argcは仮パラメータの数です。

2.17.2 条件文

条件付きコマンド: if...else...end 。これは他の言語で提供されているifコマンドと違いはありません。 endに注意してください。

2.17.3 ループ文

ループコマンド: while...end 。 gdb には、他の言語のbreakcontinueにそれぞれ対応するloop_breakloop_continueコマンドも用意されています。 endにも注目してください。

set logged on overwrite gdb.log------------表示されたログを gdb.log に保存します。
set pagination off--------------------------ページング表示機能をオフにします。

tar jtag jtag://localhost:1025--------------JTAGに接続します。

d------------------------------------------------既存のブレークポイントを削除します。

b func_a------------------------------------func_a にブレークポイントを追加します。
コマンド------------------------------------ブレークポイントの後、以下のコマンドを実行します。
  b func_b----------------------------------func_a のブレークポイントの後に、func_b にブレークポイントを追加します。
    コマンド bt full-------------------------------func_b のスタック フレームを出力します。
      c-------------------------------------実行を続行します。
    終わり
  b file.c:555------------------------------file.c の 555 行目にブレークポイント コマンドを追加します
      while 1-------------------------------次のコマンドを無限に実行します。
        次
      終わり
    終わり
  c----------------------------------------- 実行を続行して、func_b および file.c:555 ブレークポイントをトリガーします。
終わり

c-------------------------------------------------------- はプログラムが実行を継続することを意味します。

また、コマンドラインで gdb -x gdb.init bin; または gdb bin を実行してからコマンドラインで gdb.init をソースとして実行して、スクリプトを更新することもできます。

2.18. 指定したファイルにメモリをダンプする

gdb のデバッグ中に、メモリのセクションをファイルにエクスポートする必要がある場合があります。これは、dump コマンドを使用して実行できます。

コマンド形式:

バイナリメモリをダンプ FILE START STOP

たとえば、dump binary memory ./dump.bin 0x0 0x008000000 は、0x0 から 0x00800000 までのメモリ範囲を dump.bin にエクスポートします。

3. gdb+gdbserver リモートデバッグ

ターゲット ボード gdbserver + ホスト gdb リモート デバッグ方式は、パフォーマンスが制限され、gdbserver 機能のみを提供できるターゲット ボードに適しています。

リモート デバッグのためにホスト コンピューターで gdb を実行します。テスト手順は以下のとおりです。

#include <stdio.h>

void C(int *p)
{
    *p = 0x12;
}

void B(int *p)
{
    C(p);
}
void A(int *p)
{
    B(p);
}
void A2(int *p)
{
    C(p);
}
int main(int argc, char **argv)
{
    整数a;
    int *p = NULL;
    A2(&a); // A2 > C
    printf("a = 0x%x\n", a);
    A(p); // A > B > C
    0を返します。
}

ターゲット ボードは次のように設定されます: ポート 2345 を gdbserver 銅ポートとして開きます。

gdbserver:2345 テストデバッグ

ホスト上で gdb test_debug を実行し、次に tar remote 192.168.2.84.2345 を実行してリモート gdbserver に接続します。

ターゲット ボードは、「ホスト 192.168.33.77 からのリモート デバッグ」というメッセージを受信し、2 つの間の接続が成功したことを示します。

ホスト上でリモートデバッグを実行できます。続行すると、両端で取得される結果は次のとおりです。

ターゲットボードは「a=0x12」を出力した後、実行を停止します。

ホストは SIGSEGV を受信し、バックトレース情報を表示できます。問題はポインタ p が NULL を指していること、および 0 ポインタの割り当てが間違っていることにあることがわかります。

4. core+gdbによるオフライン解析

ターゲット ボード上で ulimit -c unlimited を実行し、アプリケーションを実行します。

プログラム エラーが発生すると、現在のディレクトリにコア ファイルが生成されます。

コアファイルをコピーした後、PC上でxxx-linux-gdb ./test ./coreを実行して解析します。

4.1、ライブラリファイルの読み込み

xxx-linux-gdb ./test ./core を実行した後、ライブラリ ファイルが関連付けられていない可能性があります。

ライブラリの読み込みステータスを表示するには、info sharedlibrary を使用します。

Syms 共有オブジェクトライブラリの読み取り
                        xxx.soはありません
                        /lib/libdl.so.2 なし
                        /lib/libpthread.so.0 なし
0x2ab6ec00 0x2ac09ba4 はい xxx/lib/libstdc++.so.6
                        /lib/libm.so.6 なし
0x2acec460 0x2acf626c はい xxx/lib/libgcc_s.so.1
                        /lib/libc.so.6 なし
                        /lib/ld.so.1 がありません

これは、ライブラリが配置されているパスに対応する set solib-search-path および set solib-absolute-prefix によって設定できます。

Syms 共有オブジェクトライブラリの読み取り
0x2aaca050 0x2aacc8d0 はい xxx.so
0x2aad0ad0 0x2aad17ac はい (*) xxx/lib/libdl.so.2
0x2aad8a50 0x2aae7434 はい (*) xxx/lib/libpthread.so.0
0x2ab6ec00 0x2ac09ba4 はい xxx/lib/libstdc++.so.6
0x2ac4b3d0 0x2acb1988 はい xxx/lib/libm.so.6
0x2acec460 0x2acf626c はい xxx/lib/libgcc_s.so.1
0x2ad17b80 0x2adf699e はい xxx/lib/libc.so.6
0x2aaa89e0 0x2aabf66c はい (*) xxx/lib/ld.so.1
(*): 共有ライブラリにデバッグ情報がありません。

関連するライブラリ ファイルがロードされていることがわかりますが、一部のライブラリ ファイルにはデバッグ情報がありません。

4.2. バックトレースの表示

コアダンプのバックトレースを表示するには、ビット t を使用します。より完全な情報を表示するには、ビット t full を使用します。

関数呼び出しスタックを生成するいくつかの関数

bt: すべての関数呼び出しスタック フレームに関する情報を、フレームごとに 1 行表示します。

bt n: スタック内の n フレームの情報を表示します。

bt -n: スタックの一番下に n フレームの情報を表示します。

bt full: 関数パラメータやローカル変数など、スタック内のすべてのフレームの完全な情報を表示します。

bt full n: 上記と同じ使用法です。

btフル-n

(gdb) うーん
#0 xxx/lib/libc.so.6 からの memcpy() の 0x2ad71f1e
#1 xxx/lib/libc.so.6 からの memmove() で 0x2ad71ac0
#2 0x0011f36c in std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m<unsigned char> (__first=0x34dfb008 "\377\330\377", <不完全なシーケンス \340>, __last=0x34eeea2c "", 
    ...
#3 0x0011ee22 in std::__copy_move_a<false, unsigned char*, unsigned char*> (__first=0x34dfb008 "\377\330\377", <不完全なシーケンス \340>, __last=0x34eeea2c "", __result=0x2b2013c0 "\377\330\377", <不完全なシーケンス \340>)
    xxxinclude/c++/6.3.0/bits/stl_algobase.h:386 で
#4 0x0011e7e2 in std::__copy_move_a2<false, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char> >, unsigned char*> (__first=..., __last=..., __result=0x2b2013c0 "\377\330\377", <不完全なシーケンス \340>)
    xxx/bits/stl_algobase.h:424 で
#5 std::copy<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char> >, unsigned char*> 内の 0x0011dfd2 (__first=...、__last=...、__result=0x2b2013c0 "\377\330\377"、<不完全なシーケンス \340>)
    xxx/6.3.0/bits/stl_algobase.h:456 で
#6 xxx の 0x0011c948
#7 xxx の 0x00133e08
#8 xxx/libc/lib/libpthread.so.0 からの start_thread() の 0x2aada31e
#9 0x005a11b4 ??() 内

4.3 コアダンプ保存ファイルのディレクトリと命名規則

デフォルトでは、コア ファイルは現在のアプリケーション パスに保存され、区別するために設定できます。

コアは主に /proc/sys/kernel/core_uses_pid と /proc/sys/kernel/core_pattern によって区別されます。

/proc/sys/kernel/core_uses_pid: 生成されたコア ファイルのファイル名に拡張子として pid を追加するかどうかを制御できます。追加される場合、ファイルの内容は 1 になり、追加されない場合は 0 になります。

proc/sys/kernel/core_pattern: フォーマットされたコアファイルの保存場所またはファイル名を設定できます。たとえば、元のファイルの内容は core-%e です。

echo "/tmp/core-%e-%p" > core_pattern.

生成されたコアファイルは/corefileディレクトリに保存されます。生成されたファイル名はcore-コマンド名-pid-タイムスタンプです。

パラメータのリストは次のとおりです。

%p - ファイル名にPIDを挿入
%u - 現在の uid をファイル名に挿入します
%g - 現在のGIDをファイル名に挿入
%s - コアダンプの原因となったシグナルをファイル名に挿入します
%t - コアダンプが発生したUNIX時間をファイル名に挿入します。コアファイルが生成されたUNIX時間を追加します。
%h - コアダンプが発生したホスト名をファイル名に挿入します
%e - コアダンプ実行可能ファイル名をファイル名に挿入する コマンド名を追加する

もちろん、次の方法でこれを行うこともできます。

sysctl -w kernel.core_pattern=/tmp/core-%e-%p

4.4 ulimitの使用

関数の説明: シェル プログラムのリソースを制御します。

構文: ulimit [-aHS][-c <コアファイルの上限>][-d <データセクションのサイズ>][-f <ファイルサイズ>][-m <メモリサイズ>][-n <ファイル数>][-p <バッファサイズ>][-s <スタックサイズ>][-t <CPU時間>][-u <プログラム数>][-v <仮想メモリサイズ>]

追加情報: ulimit は、シェル実行プログラムのリソースを制御するために使用できる組み込みシェル コマンドです。

パラメータ:

-a 現在のリソース制限設定を表示します。
-c <コア ファイルの上限> コア ファイルの最大値をブロック単位で設定します。
-d <データ セクション サイズ> プログラム データ セクションの最大値 (KB 単位)。
-f <ファイル サイズ> シェルが作成できる最大ファイル (ブロック単位)。
-H はリソースにハード制限、つまり管理者によって設定された制限を設定します。
-m <メモリ サイズ> は、使用可能なメモリの上限を KB 単位で指定します。
-n <ファイル数> は、同時に開くことができるファイルの最大数を指定します。
-p <バッファ サイズ> は、パイプ バッファのサイズを 512 バイト単位で指定します。
-s <スタック サイズ> スタックの上限を KB 単位で指定します。
-S リソースの弾性制限を設定します。
-t <CPU 時間> は、CPU 使用時間の上限を秒単位で指定します。
-u <プログラム数> ユーザーが開くことができるプログラムの最大数。
-v <仮想メモリ サイズ> は、使用可能な仮想メモリの上限を KB 単位で指定します。

5. GDBのヒント

5.1. 閉じる

続行するには<return>、終了するにはq<return>と入力してください---

表示内容が大きい場合、GDB はページングを強制し、表示が中断されます。ただし、これは必要ない場合があり、ページ区切りをオフに設定することで無効にすることができます。

5.2. 実行中のカーネルに接続する

実行中の Linux でクラッシュやその他の問題が発生した場合、JTAG 接続を使用して問題を特定する必要があります。

接続方法は次のとおりです。

gdb-----------------------------------------------gdb シェルに入ります。

ターゲット リモート localhost:1025-------------------gdb シェルで ip:port 経由でターゲットに接続します。

ファイル vmlinux----------------------------------------シンボルテーブルをロードします。

その後、実行ステータスをオンラインで確認できます。

上記は Linux デバッガー GDB の基本的な使用方法の詳細な内容です。Linux デバッガー GDB の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Linux で gdb を使用してコア ファイルをデバッグする方法
  • Linux での GDB 入門チュートリアル
  • Linux デバッグツール GDB の使い方に関する簡単なチュートリアル
  • gdb および gdbserver コマンドを使用した Linux アプリケーションのデバッグ
  • Linux デバッグツール strace と gdb に基づく一般的なコマンドの概要

<<:  チェックボックスの不確定プロパティの使用の紹介

>>:  CSSポジショニングによる階層関係の問題の詳細な説明

推薦する

MacにHomebrewをインストールする際の注意点

最近、Xiao Ming は新しい Mac を購入し、独自のブログ Web サイトを構築したいと考え...

HTML 画像 img にハイパーリンクを追加した後の醜い青い境界線の問題を解決する

HTML画像にハイパーリンクを追加すると醜い青い枠線が表示される次のように:解決: CSS スタイル...

MySQL の binlog ログと、binlog ログを使用してデータを回復する方法を説明します。

ご存知のとおり、binlog ログは MySQL データベースにとって非常に重要です。万が一、データ...

フォーム入力ボックスに関するWebデザインのヒント

この記事では、Web デザインにおけるフォーム入力ボックスに関するヒントとコードをいくつか紹介します...

JavaScript 履歴オブジェクトの説明

目次1. ルートナビゲーション2. 履歴状態管理API (1)ハッシュチェンジイベント(2)ポップス...

Linux サーバーに Python3 をインストールする 2 つの方法

最初の方法Alibaba Cloud および Baidu Cloud サーバーが利用可能です。 ! ...

HTMLフォーム要素の包括的な理解

以下のように表示されます。 XML/HTML コードコンテンツをクリップボードにコピー<!DO...

Nodejs は JSON 文字列を JSON オブジェクトに変換するエラー解決法

JSON 文字列を JSON オブジェクトに変換するにはどうすればいいですか? JSON.parse...

HTMLを圧縮しない理由はいくつかある

理由は簡単です。 HTML ドキュメントでは、複数の空白文字は 1 つの空白文字と同等です。つまり、...

dockerコンテナは直接実行され、pingを介してパブリックIP操作を取得します。

コンテナを通じてローカル パブリック IP アドレスを取得します。ローカル IP アドレスを使用して...

Linuxプロセス通信におけるFIFOの実装

FIFO通信(先入れ先出し)関連のないプロセス間の通信を可能にする FIFO 名前付きパイプ。パイプ...

サブセットかどうかを判断するためのMySQLメソッドの手順

目次1. 問題2. 解決策オプション1:オプション2: 1. 問題この話は、エラーと脱落率を照会する...

Linux プラットフォームの MySQL でリモート ログインを有効にする

開発中、MySQL へのリモートアクセスでよく問題に遭遇します。そのたびに検索する必要があり、面倒に...

モバイル開発チュートリアル: ピクセル表示の問題の概要

序文モバイル端末の開発の過程で、モバイル端末のディスプレイはデスクトップ端末のディスプレイとは一般的...

Linux サービス管理の 2 つの方法、service と systemctl の詳細な説明

1.サービスコマンドサービスコマンドは実際には/etc/init.dディレクトリに移動し、関連プログ...