linux GDB and GDB Sever

news2024/11/18 7:27:31

概念:

GDB(GNU Debugger)是一个用于调试程序的强大工具。它是GNU项目的一部分,支持多种编程语言,包括C、C++等。GDB 提供了一组命令和功能,允许跟踪检查程序的内部状态,跟踪代码的执行过程,以及定位和修复程序中的错误。

gdb和gdb sever

GDB(GNU Debugger)

  • gdb 用于本地调试程序。它允许程序员查看程序的运行状态、检查变量和内存、设置断点等,以便在代码中找到和修复问题。
  • 使用 gdb 时,你在本地计算机上运行 gdb,并且该调试器直接与正在调试的程序进行交互。

GDB Server(gdbserver)

  • gdbserver 是 GDB 的另一部分,用于远程调试。它允许你在目标计算机上运行一个小型的 GDB 服务器,然后在本地计算机上运行gdb 与之连接。
  • 通过 gdbserver,你可以在嵌入式系统或远程计算机上调试程序,而不需要将整个 GDB 调试器放在目标系统上。
  • 这种分离的方法对于嵌入式系统等资源受限的环境非常有用,允许在目标系统上运行轻量级的 gdbserver,而在开发机上运行完整版的 gdb 进行调试。

作用

  1. 调试程序: GDB的主要作用是帮助程序员识别和解决程序中的错误(bugs)。它允许开发者在程序执行时停下来,检查变量的值,查看函数调用堆栈,设置断点,并逐步执行代码。
  2. 变量和内存查看:GDB 允许开发者检查程序运行时的变量的值和内存的内容。这对于理解程序的状态以及发现潜在问题非常有用。
  3. 设置断点: 开发者可以在程序中设置断点,使得程序在执行到达特定的位置时停下来。这有助于逐步调试程序并检查特定的代码段。
  4. 单步执行:GDB 允许开发者逐步执行程序,一次执行一行代码或一次执行一个函数。这对于追踪程序的执行流程非常有用。
  5. 追踪函数调用:GDB 能够跟踪程序中的函数调用,显示函数调用关系,帮助开发者理解程序的执行路径。
  6. 查找内存错误:GDB 能够帮助开发者查找程序中的内存错误,如访问未分配内存、内存溢出等问题。
  7. 多线程调试:GDB 支持调试多线程程序,允许开发者查看和调试不同线程的执行状态。
  8. 核心转储分析:当程序发生崩溃时,GDB 可以分析核心转储文件,帮助开发者定位问题的根本原因。

GDB和IDE差别

  • 各有好处,并且IDE在不考虑环境的情况下,更容易上手
  • 基于 Linux 服务器等的无图形界面开发,使用 Vim+GDB 可以在任意一台电脑上直接调试,不用花时间安装复杂的 IDE 环境。

主要包含如下区别:

  • 命令行界面 vs 图形用户界面
  • 功能的可视化和图形化展示
  • 集成性和便利性
  • 快捷键和工具栏
  • 平台和语言支持

总体而言,使用 GDB 和使用 IDE 中的调试工具之间的选择通常取决于个人偏好、项目需求以及开发环境。

gdb 调试段错误代码demo

#include <stdio.h>

void accessInvalidMemory() {
    int *ptr = NULL; // 故意将指针设置为NULL
    *ptr = 42;       // 试图访问NULL指针
}
int main() {
    accessInvalidMemory(); // 调用会导致Segmentation fault的函数
    return 0;
}

定位流程与操作

@ubuntu:$ gcc -g Segmentation_fault.c -o Segmentation_fault
@ubuntu:GDB_debug$ gdb ./Segmentation_fault -q
Reading symbols from ./Segmentation_fault...done.
(gdb) b main
Breakpoint 1 at 0x617: file Segmentation_fault.c, line 9.
(gdb) list
1       #include <stdio.h>
2
3       void accessInvalidMemory() {
4           int *ptr = NULL; // 故意将指针设置为NULL
5           *ptr = 42;       // 试图访问NULL指针
6       }
7
8       int main() {
9           accessInvalidMemory(); // 调用会导致Segmentation fault的函数
10          return 0;
(gdb) r
Starting program: GDB_debug/Segmentation_fault

Breakpoint 1, main () at Segmentation_fault.c:9
9           accessInvalidMemory(); // 调用会导致Segmentation fault的函数
(gdb) s
accessInvalidMemory () at Segmentation_fault.c:4
4           int *ptr = NULL; // 故意将指针设置为NULL
(gdb) n
5           *ptr = 42;       // 试图访问NULL指针
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x000055555555460a in accessInvalidMemory () at Segmentation_fault.c:5
5           *ptr = 42;       // 试图访问NULL指针
(gdb) bt
#0  0x000055555555460a in accessInvalidMemory () at Segmentation_fault.c:5
#1  0x0000555555554621 in main () at Segmentation_fault.c:9
(gdb) n
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb) n
The program is not being run.

结论
查看调用栈

(gdb) bt
#0  0x000055555555460a in accessInvalidMemory () at Segmentation_fault.c:5
#1  0x0000555555554621 in main () at Segmentation_fault.c:9

问题出在:函数accessInvalidMemory,代码的第五行

说明与解释

  • bt是backtrace的缩写,可以查看调用栈
  • r是run的缩写
  • n是next的缩写
  • s是step的缩写
  • b 是break的缩写
  • quit 退出gdb调试,缩写为q

为什么不一直用next?还用step?

  • next执行当前函数的所有指令,而step可以让进入段错误函数后再第一行停下来,可以定位到具体到某一行出现的问题

GDB多线程调试

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *thread_function(void *arg) {
    for (int i = 0; i < 5; ++i) {
        printf("Thread %ld: Iteration %d\n", (long)arg, i);
        sleep(1);
    }
    return NULL;
}

int main() {
    pthread_t thread1, thread2;

    // 创建两个线程
    pthread_create(&thread1, NULL, thread_function, (void *)1);
    pthread_create(&thread2, NULL, thread_function, (void *)2);

    // 等待线程结束
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    return 0;
}

编译

gcc -g multithread_demo.c -o multithread_demo -lpthread

执行

gdb ./multithread_demo -q

想要完成的调试方法

1、查看整体进程中的线程执行结果

@ubuntu:$ gdb ./multithread_demo -q
Reading symbols from ./multithread_demo...done.
(gdb) b main
Breakpoint 1 at 0x81d: file multithread_demo.c, line 13.
(gdb) run
Starting program: GDB_debug/multithread_demo
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main () at multithread_demo.c:13
13      int main() {
(gdb) n
17          pthread_create(&thread1, NULL, thread_function, (void *)1);
(gdb) n
[New Thread 0x7ffff77c2700 (LWP 335)]
18          pthread_create(&thread2, NULL, thread_function, (void *)2);
(gdb) info threads
Id   Target Id         Frame
- 1    Thread 0x7ffff7fdb740 (LWP 130537) "multithread_dem" main () at multithread_demo.c:18
(gdb) n
Thread 1: Iteration 1
Thread 2: Iteration 0
Thread 1: Iteration 2
Thread 2: Iteration 1
Thread 1: Iteration 3
Thread 2: Iteration 2
Thread 1: Iteration 4
Thread 2: Iteration 3
[Thread 0x7ffff77c2700 (LWP 335) exited]
22          pthread_join(thread2, NULL);
(gdb) n
Thread 2: Iteration 4
[Thread 0x7ffff6fc1700 (LWP 1407) exited]
24          return 0;
(gdb) n
25      }
(gdb) n
[Inferior 1 (process 130537) exited normally]
(gdb) n
The program is not being run.

2、子线程被创建后,gdb跟踪子线程及主线程


@ubuntu:GDB_debug$ gdb ./multithread_demo -q
Reading symbols from ./multithread_demo...done.
(gdb) set detach-on-fork off
(gdb) b main
Breakpoint 1 at 0x81d: file multithread_demo.c, line 13.
(gdb) run
Starting program: GDB_debug/multithread_demo
[Thread debugging using libthread_db enabled]
13      int main() {
(gdb) n
17          pthread_create(&thread1, NULL, thread_function, (void *)1);
(gdb) n
[New Thread 0x7ffff77c2700 (LWP 9522)]
Thread 1: Iteration 0
18          pthread_create(&thread2, NULL, thread_function, (void *)2);
(gdb) n
[New Thread 0x7ffff6fc1700 (LWP 9523)]
Thread 2: Iteration 0
Thread 2: Iteration 1
Thread 2: Iteration 2
Thread 2: Iteration 3
Thread 2: Iteration 4
8               sleep(1);
(gdb)
6           for (int i = 0; i < 5; ++i) {
(gdb)
7               printf("Thread %ld: Iteration %d\n", (long)arg, i);
(gdb)
Thread 1: Iteration 1
8               sleep(1);
(gdb)
6           for (int i = 0; i < 5; ++i) {
(gdb)
7               printf("Thread %ld: Iteration %d\n", (long)arg, i);
(gdb)
Thread 1: Iteration 2
8               sleep(1);
(gdb)
6           for (int i = 0; i < 5; ++i) {
(gdb)
7               printf("Thread %ld: Iteration %d\n", (long)arg, i);
(gdb)
Thread 1: Iteration 3
8               sleep(1);
(gdb)
6           for (int i = 0; i < 5; ++i) {
(gdb)
7               printf("Thread %ld: Iteration %d\n", (long)arg, i);
(gdb)
Thread 1: Iteration 4
8               sleep(1);
(gdb)
6           for (int i = 0; i < 5; ++i) {
(gdb)
10          return NULL;
(gdb)
11      }

命令解释

  • set detach-on-fork off 告诉 GDB 在子进程(或线程)分离时不要自动分离调试器,默认情况下,GDB 会在程序中发生
    fork 时自动分离调试器,这可能导致你失去对子进程的控制,所以我一般会设置为off
  • show detach-on-fork可以看当前的设置状态

GDB多进程调试

#include <stdio.h>
#include <unistd.h>
int main()
{
    pid_t pid = fork();
    if(pid == 0)
    {
        int num =10;
        while(num==10){
            sleep(2);
            printf("this 1is child,pid = %d\n",getpid());
        }
        
        printf("this 2is child,pid = %d\n",getpid());
        printf("this 3is child,pid = %d\n",getpid());
    }
    else
    {
            int mnum=5;
            while(mnum==5){
            sleep(5);
            printf("this 4is parent,pid = %d\n",getpid());
        }
        
    }
    return 0;
}

编译

gcc -g multiprocess_demo_2.c -o multiprocess_demo_2

gdb 跟踪子进程

@ubuntu:GDB_debug$ gcc -g multiprocess_demo_2.c -o multiprocess_demo_2
@ubuntu:GDB_debug$ gdb ./multiprocess_demo_2 -q
Reading symbols from ./multiprocess_demo_2...done.
(gdb) b main
Breakpoint 1 at 0x722: file multiprocess_demo_2.c, line 5.
(gdb) set follow-fork-mode child
(gdb) r
Starting program: /home/xj/Desktop/huangrui/project_1/GDB_debug/multiprocess_demo_2

Breakpoint 1, main () at multiprocess_demo_2.c:5
5           pid_t pid = fork();
(gdb) n
[New process 109167]
[Switching to process 109167]
main () at multiprocess_demo_2.c:6
6           if(pid == 0)
(gdb) info inferiors
  Num  Description       Executable
  1    <null>            GDB_debug/multiprocess_demo_2
* 2    process 109167    GDB_debug/multiprocess_demo_2
(gdb) this 4is parent,pid = 109163
this 4is parent,pid = 109163
n
8               int num =10;
(gdb) n
9               while(num==10){
(gdb) this 4is parent,pid = 109163
n
10                  sleep(2);
(gdb) n
11                  printf("this 1is child,pid = %d\n",getpid());
(gdb) this 4is parent,pid = 109163
p num=this 4is parent,pid = 109163
9
$1 = 9
(gdb) n
this 1is child,pid = 109167
9               while(num==10){
(gdb) n
14              printf("this 2is child,pid = %d\n",getpid());
(gdb) n
this 2is child,pid = 109167
15              printf("this 3is child,pid = %d\n",getpid());
(gdb) this 4is parent,pid = 109163
n
this 3is child,pid = 109167
26          return 0;
(gdb) n
27      }(gdb) nthis 4is parent,pid = 109163

__libc_start_main (main=0x55555555471a <main>, argc=1, argv=0x7fffffffe328, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe318)
    at ../csu/libc-start.c:344
344     ../csu/libc-start.c: No such file or directory.
(gdb) n
[Inferior 2 (process 109167) exited normally]
(gdb) n
The program is not being run.
(gdb) quitthis 4is parent,pid = 109163

set follow-fork-mode的作用:set follow-fork-mode parent 是 GDB 的一个命令,用于在多进程调试时控制在 fork() 调用之后 GDB 应该跟踪哪个进程。

  • set follow-fork-mode parent: 设置 GDB 在 fork()调用后继续跟踪父进程,而不是默认的子进程。这意味着在程序执行 fork() 后,GDB将继续调试父进程,而子进程将被分离(detach)。
  • set follow-fork-mode child: 设置 GDB 在 fork()调用后继续跟踪子进程,而不是默认的父进程。这意味着在程序执行 fork() 后,GDB 将继续调试子进程,而父进程将被分离。
  • set follow-fork-mode ask: 设置 GDB 在 fork() 调用后询问用户要跟踪哪个进程。GDB 将在每次 fork() 发生时等待用户输入,以确定是跟踪父进程还是子进程。

解释
在这里插入图片描述

补充:

  • 在 GDB 中,使用 p 命令(print 的缩写)不仅可以用来查看变量的值,还可以用来修改变量的值。当你执行 p num=9
    时,实际上是在给变量 num 赋予新的值。

前面是单子进程的调试

那如果我父进程创建多个子进程,应该如何调试呢?

#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid1, pid2;

    pid1 = fork();
    if (pid1 == 0) {
        // 子进程1
        printf("Child Process 1 (PID: %d)\n", getpid());
        // 子进程1的工作
    } else {
        pid2 = fork();
        if (pid2 == 0) {
            // 子进程2
            printf("Child Process 2 (PID: %d)\n", getpid());
            // 子进程2的工作
        } else {
            // 父进程
            printf("Parent Process (PID: %d)\n", getpid());
            // 父进程的工作
            // 父进程通常需要等待子进程结束
            waitpid(pid1, NULL, 0);
            waitpid(pid2, NULL, 0);
        }
    }
    return 0;
}

调试步骤(步骤有删减):

@ubuntu:GDB_debug$ gdb ./multiprocess_demo -q
Reading symbols from ./multiprocess_demo...done.
(gdb) b main
Breakpoint 1 at 0x722: file multiprocess_demo.c, line 7.
(gdb) b fork
Breakpoint 2 at 0x5f0
(gdb) set detach-on-fork off
(gdb) set follow-fork-mode child
(gdb) catch fork
Catchpoint 3 (fork)
(gdb) run
Starting program: GDB_debug/multiprocess_demo

Breakpoint 1, main () at multiprocess_demo.c:7
7           pid1 = fork();
(gdb) n

Breakpoint 2, __libc_fork () at ../sysdeps/nptl/fork.c:49
49      ../sysdeps/nptl/fork.c: No such file or directory.
(gdb) n
Catchpoint 3 (forked process 109279), 0x00007ffff7ac67cc in __libc_fork () at ../sysdeps/nptl/fork.c:135
135     in ../sysdeps/nptl/fork.c
(gdb)
[New process 109279]
Reading symbols from GDB_debug/multiprocess_demo...done.
Reading symbols from /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.27.so...done.
Reading symbols from /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.27.so...done.
__libc_fork () at ../sysdeps/nptl/fork.c:142
142     ../sysdeps/nptl/fork.c: No such file or directory.
(gdb) info inferiors
  Num  Description       Executable
  1    process 109275    GDB_debug/multiprocess_demo
* 2    process 109279    GDB_debug/multiprocess_demo
(gdb) n
main () at multiprocess_demo.c:8
8           if (pid1 == 0) {
(gdb)
10              printf("Child Process 1 (PID: %d)\n", getpid());
(gdb) n
Child Process 1 (PID: 109279)
28          return 0;
(gdb) n
29      }
(gdb) n
[Inferior 2 (process 109279) exited normally]
(gdb) n
The program is not being run.
(gdb) info inferiors
  Num  Description       Executable
  1    process 109275    GDB_debug/multiprocess_demo
* 2    <null>           GDB_debug/multiprocess_demo
(gdb) inferior 1
[Switching to inferior 1 [process 109275] (GDB_debug/multiprocess_demo)]
[Switching to thread 1.1 (process 109275)]
#0  0x00007ffff7ac67cc in __libc_fork () at ../sysdeps/nptl/fork.c:135
135     ../sysdeps/nptl/fork.c: No such file or directory.
(gdb) n
main () at multiprocess_demo.c:8
8           if (pid1 == 0) {
(gdb)
13              pid2 = fork();
(gdb) n
(gdb)
[New process 109280]
Reading symbols from GDB_debug/multiprocess_demo...done.
Reading symbols from /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.27.so...done.
Reading symbols from /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.27.so...done.
__libc_fork () at ../sysdeps/nptl/fork.c:142
142     ../sysdeps/nptl/fork.c: No such file or directory.

(gdb)
main () at multiprocess_demo.c:14
14              if (pid2 == 0) {
(gdb)
16                  printf("Child Process 2 (PID: %d)\n", getpid());
(gdb)
Child Process 2 (PID: 109280)
28          return 0;
(gdb)
29      }
(gdb)
[Inferior 3 (process 109280) exited normally]
(gdb) info inferiors
  Num  Description       Executable
  1    process 109275    GDB_debug/multiprocess_demo
 * 3    <null>            GDB_debug/multiprocess_demo
(gdb) n
The program is not being run.
(gdb) info inferiors
  Num  Description       Executable
  1    process 109275    GDB_debug/multiprocess_demo
 * 3    <null>           GDB_debug/multiprocess_demo
(gdb) continue
The program is not being run.
(gdb) n
The program is not being run.
(gdb) info inferiors
  Num  Description       Executable
  1    process 109275   GDB_debug/multiprocess_demo
 * 3    <null>            GDB_debug/multiprocess_demo
(gdb) inferior 1
[Switching to inferior 1 [process 109275] (GDB_debug/multiprocess_demo)]
[Switching to thread 1.1 (process 109275)]
#0  0x00007ffff7ac67cc in __libc_fork () at ../sysdeps/nptl/fork.c:135
135     ../sysdeps/nptl/fork.c: No such file or directory.
main () at multiprocess_demo.c:14
14              if (pid2 == 0) {
(gdb)
20                  printf("Parent Process (PID: %d)\n", getpid());
(gdb)
Parent Process (PID: 109275)
23                  waitpid(pid1, NULL, 0);
(gdb) n
24                  waitpid(pid2, NULL, 0);
(gdb) n
28          return 0;
(gdb) info inferiors
  Num  Description       Executable
 * 1    process 109275    GDB_debug/multiprocess_demo
(gdb) n
29      }
(gdb) n
[Inferior 1 (process 109275) exited normally]
(gdb) n
The program is not being run.

如下是对上面的进行的备注
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

再次逻辑与命令说明

  • set follow-fork-mode child:fork后跟踪子进程
  • set detach-on-fork off不自动分离调试器
  • break fork 设置断点在 fork() 处
  • catch fork 在 fork() 处停下,并切换到子进程
  • continue 继续执行,这将在子进程中停下
  • info inferiors 查看当前进程
  • inferiors 2 切换到指定进程,例如第二个进程

这样就可以单独的调试某个进程了

gdb sever的连接调试

在这里我简单说明下连接的三个基本流程流程:

  1. 在目标机器上启动 GDB Server:gdbserver :1234 /path/to/your/target/program
  2. 在本地机器上启动 GDB 并连接到 GDB Server:gdb /path/to/your/target/program,在 GDB 中连接到 GDB Server:target remote <target_system_ip>:1234
  3. 在本地 GDB 中进行调试

这个内容的实操我会在后面的文档中体现出来,一篇文档内容过多,比较冗余

对于前面的GDB的8个作用基本就覆盖了,还差一个core dump的就让读者自己完成吧,主要就是做一个抛砖引玉的作用,嘻嘻

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1390194.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7.5 MySQL对数据的基本操作(❤❤❤)

7.5 MySQL对数据的基本操作 1. 提要2. 数据添加2.1 insert语法2.2 insert 子查询2.3 ignore关键字 3. 数据修改3.1 update语句3.2 update表连接 4. 数据删除4.1 delete语句4.2 delete表连接4.3 快速删除数据表全部数据 1. 提要 2. 数据添加 2.1 insert语法 2.2 insert 子查询 …

vivado 添加现有IP文件、生成IP

添加现有IP文件 作为从AMD IP目录添加和自定义IP的替代方案&#xff0c;您可以直接添加XCI或XCIX文件。此过程不同于从按以下方式编目&#xff1a; •XCI或XCIX文件可能是早期版本&#xff0c;也可能是相同或完全自定义的版本AMD IP目录中发现的类似IP。 •XCI或XCIX文件可能…

【linux】systemctl控制系统服务启动与关闭

systemctl简介 systemctl是一个在linux系统中&#xff0c;管理系统服务的命令。它通常是启动与关闭像防火墙&#xff0c;网络&#xff0c;数据库这类不是直接的软件&#xff0c;而是给软件提供支持的服务。 但是值得注意的是&#xff0c;并不是所有服务都可以用它管理&#x…

Vue学习笔记3--全局事件总线

Vue学习笔记3—全局事件总线 1.全局事件总线可以实现任意组件间通信 X需具备的条件&#xff1a; 所有的组件都要能看见X可以调用$on $off $emitVue.prototype.x {a:1, b:2} 可以被所有组件看见VueComponent.protoype.proto Vue.prototype组件实例对象(vc)可以访问到Vue原型上…

【.NET Core】C#预处理器指令

【.NET Core】C#预处理器指令 文章目录 【.NET Core】C#预处理器指令一、概述二、可为空上下文&#xff08;#nullable&#xff09;三、条件编译2.1 定义DEBUG是编译代码2.2 未定义MYTEST时&#xff0c;将编译以下代码 四、定义符号五、定义区域六、错误和警告信息 一、概述 预…

关于 ant-design-vue resetFields 失效

关于 ant-design-vue resetFields 失效 背景&#xff1a; 遇到这样的问题使用ant-design-vue useForm来制作表单的时候&#xff0c;resetFields()失效 场景&#xff1a; 编辑 -赋值 新增-初始值&#xff08;问题点&#xff1a;新增的时候他就不初始化&#xff09; 方案&…

【STM32】STM32学习笔记-USART串口收发HEX和文本数据包(29)

00. 目录 文章目录 00. 目录01. 串口简介02. 串口收发HEX数据包接线图03. 串口收发HEX数据包示例104. 串口收发HEX数据包示例205. 串口收发文本数据包接线图06. 串口收发文本数据包示例07. 程序示例下载08. 附录 01. 串口简介 串口通讯(Serial Communication)是一种设备间非常…

智能搬运机器人作为一种新型的物流技术

随着物流行业的快速发展&#xff0c;货物转运的效率和准确性成为了企业竞争的关键因素之一。智能搬运机器人作为一种新型的物流技术&#xff0c;已经在许多企业中得到了广泛应用。本文将介绍富唯智能智能搬运机器人在物流行业的应用和优势。 在实际应用中&#xff0c;智能搬运机…

在visual studio中调试时无法查看std::wstring

1.问题 在调试的时候发现std::wstring类型的变量查看不了&#xff0c;会显示(error)|0&#xff0c;百思不得其解。 2.解决方法 参考的&#xff1a;vs2015调试时无法显示QString变量的值&#xff0c;只显示地址_vs调试qstring的时候如何查看字符串-CSDN博客 在工具/选项/调试…

transfomer中Multi-Head Attention的源码实现

简介 Multi-Head Attention是一种注意力机制,是transfomer的核心机制,就是图中黄色框内的部分. Multi-Head Attention的原理是通过将模型分为多个头&#xff0c;形成多个子空间&#xff0c;让模型关注不同方面的信息。每个头独立进行注意力运算&#xff0c;得到一个注意力权…

弟12章 网络编程

文章目录 网络协议概述 p164TCP协议与UDP协议的区别 p165TCP服务器端代码的编写 p166TCP服务器端流程 TCP客户端代码的编写 p167TCP客户端流程主机和客户端的通信流程 tcp多次通信服务器端代码 p168TCP多次通信客户端代码 p169UDP的一次双向通信 p170udp通信模型udp接收方代码u…

6 - 常用工具类

目录 1. Scanner 扫描控制台输入 1.1 扫描控制台输入 1&#xff09;nextLine 2&#xff09;nextInt 3&#xff09;其他方法 1.2 扫描文件 1.3 查找匹配项 2. Arrays 数组工具 2.1 创建数组 1&#xff09;copyOf 2&#xff09;copyOfRange 3&#xff09;fill 2.2 比…

Ubuntu共享文件到win

Ubuntu共享文件到win 1、安装samba sudo apt-get install samba samba-common2、创建一个共享文件夹&#xff0c;并设置777权限 mkdir /home/qyh/share sudo chmod 777 /home/qyh/share我的用户名&#xff1a;qyh。 3、添加用户及密码 sudo smbpasswd -a qyh4、修改配置文…

.NET国产化改造探索(三)、银河麒麟安装.NET 8环境

随着时代的发展以及近年来信创工作和…废话就不多说了&#xff0c;这个系列就是为.NET遇到国产化需求的一个闭坑系列。接下来&#xff0c;看操作。 上一篇介绍了如何在银河麒麟操作系统上安装人大金仓数据库&#xff0c;这篇文章详细介绍下在银河麒麟操作系统上安装.NET8环境。…

Spring基础属性一览:注释、对象装配、作用域、生命周期

在Spring中想要更简单的存储和读取对象的核心是使用注解&#xff0c;也就是我们接下来要学的Spring中相关注解。 之前我们存储Bean时&#xff0c;需要在自己添加的配置文件中添加一行bean才行&#xff1a; 而现在我们只需要一个注解就可以替代之前要写的一行配置的繁琐了。 …

避免C#WindowForm编写的程序重复打开--问题解决

目录&#xff1a; 一&#xff0c;问题描述二&#xff0c;问题解决 一&#xff0c;问题描述 ❄️当你经常使用程序或者开发程序的时候&#xff0c;可能经常都会遇到一个问题&#xff1a;就是程序exe文件当多次点击后&#xff0c;无论是否及时加载&#xff0c;都会产生原本程序的…

Elasticsearch_8.11.4_kibana_8.11.4_metricbeat_8.11.4安装及本地部署_ELK日志部署

文章目录 Elasticsearch_8.11.4_kibana_8.11.4_metricbeat_8.11.4安装及本地部署_ELK日志部署分布式引擎Elasticsearch_8.11.4安装及本地部署系统环境要求1 Windows 安装 Elasticsearch下载完成后进行解压,进入 bin 目录,找到elasticsearch.bat脚本文件执行一键启动.启动都选允…

什么是技术架构?架构和框架之间的区别是什么?怎样去做好架构设计?(二)

什么是技术架构?架构和框架之间的区别是什么?怎样去做好架构设计?(二)。 技术架构是对某一技术问题(需求)解决方案的结构化描述,由构成解决方案的组件结构及之间的交互关系构成。广义上的技术架构是一系列涵盖多类技术问题设计方案的统称,例如部署方案、存储方案、缓存…

Java重修第六天—面向对象3

通过学习本篇文章可以掌握如下知识 1、多态&#xff1b; 2、抽象类&#xff1b; 3、接口。 之前已经学过了继承&#xff0c;static等基础知识&#xff0c;这篇文章我们就开始深入了解面向对象多态、抽象类和接口的学习。 多态 多态是在继承/实现情况下的一种现象&#xf…

网络共享服务

存储类型&#xff1a;直连式&#xff08;DAS&#xff09;:距离最近&#xff0c;存储设备且直接连接到服务器上 存储区域网络&#xff08;SAN&#xff09;&#xff1a;适用于大型应用或数据库系统&#xff0c;可以使用文件的空间&#xff0c; 以及管理空间…