gdb 调试入门-bcc&perf-tools

linux 挂死问题定位分析 1.生成coredump 文件 根据生成的coredump文件,下载到编译环境中,结合gdb查找符号位,定位挂死位置 /opt/toolchains/gcc-4.7.3-cmc-201308-20140423/bin/mips-linux-uclibc-gdb ./linux_cmts_sym coredump GNU gdb (GDB) 7.5.1 Copyright (C) 2012 阅读详情

bcc&perf-tools

有空要研究一下这两个工具的使用方法

没想到Brendan Gregg这样的大牛,会写出这样一篇gdb tutorials文章:gdb Debugging Full Example (Tutorial): ncurses 。但可能正如文章开头所说,大牛对网上的gdb文章都不太满意,所以才有了这篇高质量指南,gdb入门者的福音。—— 何登成

如果你是系统管理员,但还不认识 Brendan Gregg,那网上流传甚广的 3 张 Linux 性能工具图(链接),你应该看过的。—— 伯小乐。

                                                                    brendan-gregg

( Brendan Gregg)



gdb 调试 ncurses 全过程:

发现网上的“gdb 示例”只有命令而没有对应的输出,我有点不满意。gdb 是 GNU 调试器,Linux 上的标配调试器。当我看 Greg Law 在 CppCon 2015 上的演讲《给我 15 分钟,我将改变你的对 GDB 的认知》的时候,我想起了示例输出的不足,幸运的是,这次有输出!这 15 分钟太值了。

它也启发我去分享一个完整的 gdb 调试实例,包含输出和每个步骤,甚至钻牛角尖的情况。这不是一个特别有趣或奇怪的问题,只是常规的 gdb 调试会话。但它包含了基础的东西可以勉强作为教程使用,记住 gdb 里还有很多东西我这里没用到。

我会以 root 权限运行下面的命令,因为我在调试一个工具,它需要 root 权限(目前)。需要的时候可用 sudo 获取 root 权限。你也没必要通读全篇︰ 我已列出每一步,你可以浏览它们找感兴趣的看。

1. 问题概述

BPF 工具箱里的 bcc 工具集有一个对cachetop.py 的 pull 请求,它通过程序使用 top-like display 显示 page cache 的统计。太好了 !然而,当我测试它时,遇到了段错误︰

注意它说的是“段错误”,不是“段错误(核心已转储)”。我想要一个核心转储文件用来调试。(核心转储文件是进程内存的拷贝 – 这个名字来源于磁芯存储器时代 – 可用调试器分析)

分析核心转储文件是一种方法,但不是调试这个问题的唯一方法。我可以在 gdb 中运行此程序,来检查这个问题。我也可以在段错误发生时,用外部追踪器去抓数据和栈帧。我们从核心转储文件入手。

2. 解决核心转储问题

我检查一下核心转储的设置:

ulimit -c 显示核心转储文件大小的最大值,这里是零:禁止核心转储(对于本进程和它的子进程)。

/proc/…/core_pattern 仅仅被设为 “core”,表示会在当前目录下生成一个文件名为 “core” 的 核心转储文件。目前这样就行了,但是我要演示如何把它设置为全局位置。

你可以进一步定制 core_pattern;例如,%h 为主机名,%t 为转储的时间。这些选项被写在 Linux 内核源码 Documentation/sysctl/kernel.txt中。

要使 core_pattern 保持不变,重启之后仍然有效,你可以通过设置 /etc/sysctl.conf 里的 “kernel.core_pattern” 实现。

再来一次:

好多了:我们有了自己的核心转储文件。

3. 启动 GDB

现在我要用 gdb 启动目标程序(用 shell 替换符,”`”,不过在你确定能用的情况下,也可指定完整路径),和核心转储文件:

最后两行很有趣:它告诉我们这个段错误发生在 libncursesw 库里 doupdate() 函数中。可以先在网上搜一下,以防这是个很常见的问题。我搜了一下,可是没发现一个常见的原因。

我已经猜到 libncursesw 是什么了,如果你对它很陌生,它在 “/lib” 目录下以 “.so.*” 结尾表明这是一个动态库文件,可能有 man 手册、网站、包描述等。

我是碰巧在 Ubuntu 上调试,但用什么 Linux发行版对使用 gdb 并没有影响。

4. 回溯

栈回溯显示我们是如何到达失败点的,通常足够帮助我们确定常见的问题。bt (backtrace的简写)常常是我在 gdb 中使用的第一条命令:

从下往上,按照从父函数到子函数的顺序看。有 “??” 的地方是因为符号解析失败。遍历栈 – 用来生成栈帧 — 也会失败。在这种情况下你可能会看到一个正常的栈帧,跟着一个小数值的假地址。如果符号或栈破损很严重,导致无法理解栈回溯,这里有几个常用的办法来修复:安装 debug info 包(给 gdb 提供更多的符号,让它来做基于 DWARF 的栈遍历),或者重新用源码编译(-fno-omit-frame-pointer -g)一个带帧指针和调试信息的版本。以上大多数 “??”
可以通过安装 python-dbg 包来修复。

这些栈看起来不太有用:帧 5 到 17 (左边的索引)在 Python 内部,虽然还看不到 Python 方法。帧 4 是 _curses 库,然后就到了 libncursesw。看起来调用顺序是 wgetch()->wrefresh()->doupdate()。根据函数名来看,我猜是刷新窗口。为什么会导致核心转储 呢?

5. 反汇编

我从反汇编发生段错误的函数 doupdate() 开始:

部分输出。(我也可以只输入 “disas” 它会默认反汇编 doupdate )

“=>” 指向段错误地址,此处是一条 mov 指令 mov 0x10(%rsi),%rdi:从%rsi中指向内存地址的值加偏移量 0x10 处取值,送到 %rdi 寄存器中。接下来我会检查寄存器的状态。

6. 查看寄存器

使用 i r(info registers 的简写)打印寄存器值:

哦,%rsi是零,这就是我们的问题所在!零不太可能是有效地址,并且解引用一个未初始化的指针或空指针引起的段错误是常见的软件 bug。

7. 内存映射

你可以使用 i proc m (info proc mappings 的简写)核查零是不是有效地址:

第一个有效的虚拟地址是 0x400000。任何小于它的地址都是非法的,这些地址如果被引用,就会引起段错误。

目前有几种不同的方式可做进一步分析。我先一步一步的看指令。

8. 断点

先回到反汇编:

看这四条指令:好像是从栈中取东西放到 %rax,然后解引用 %rax 到 %rsi,再将 %eax 置零( xor 是一个优化,替换掉移动 0 的动作),最后将 %rsi 解引用再加一个偏移,不过我们知道 %rsi 是零。这几条指令用来访问数据结构。 可能 %rax 会很有趣,但是它已经被前面的指令置零,所以我们在核心转储文件的寄存器里看不到它的值。

我可以在 doupdate+289 下个断点,然后逐条指令查看寄存器的值如何变化。首先,我需要启动 gdb 把程序跑起来:

现在用 b (break 的简写)来下断点:

哦。我想演示这个错误来解释为什么我们经常以在主函数设置断点作为开始,因为这时候符号可能被加载,可以设置感兴趣的断点。我直接在 doupdate 函数设断点,避开这个问题,一旦断点被触发就设置加了偏移的断点。

我们到了断点处。

如果你之前没有做这些,r (run) 命令会把参数传给我们早先在命令行指定的 gdb 目标(python)。这样的话程序会以执行 “python cachetop.py” 结束。

9. 单步调试

我跳到下一条指令(si,stepi的简写),然后检查寄存器:

又一条线索。所以我们解引用的空指针好像是一个叫 “cur_term” 的符号(p/a 是 print/a 的简写,这里 “/a” 指以地址的形式)。考虑到这是 ncurses, 是我们的环境变量 TERM 设置有问题吗?

我试过将其设置为 vt100 并运行程序,还是遇到了同样的段错误。

注意我只是在 doupdate() 第一次被调用的时候查看了寄存器,但是它可以被多次调用,所以问题可能出在后边的调用中。我可以通过执行 c( continue 的简写)一步步到达出问题的地方。如果它被调用几次的话这样做是可行的,如果它被调用几千次的话我得用别的办法。(我会在 15 节的里介绍。)

10. 回退

gdb 有一个超棒的功能叫回退,Greg Law 在他的演讲中提到过。这里有一个例子。

我再启动一个 python 会话,从头演示:

和之前一样我在 doupdate 下断点,一旦触发,我就启动 recording,然后继续运行程序直到崩溃。Recording 会增加相当大的开销,所以我不想在主函数里就将它打开。

这里我可以逐行或逐条指令的回退。它通过播放我们记录的寄存器状态来工作。我回退两条指令,然后打印寄存器值:

所以,又找到了 “cur_term” 的线索。我很想看这里的源代码,但我将从调试信息入手。

11. 调试信息

这是 libncursesw,我没有安装调试信息(Ubuntu):

我把它装上:

太好了,版本匹配。那么现在我们的段错误是什么样子呢?

栈回溯看起来不太一样:我们确实不在 doupdate() 里边,而是在 ClrBlank() 中,它内联在 ClrUpdate() 里,ClrUpdate() 又内联在 doupdate() 中。

现在我真的要看源码了。

12. 源代码

安装了调试信息之后,gdb 可以同时列出源码和汇编:

好极了!看 “=>” 和它上边的代码。所以我们的段错误发生在 “if (back_color_erase)” ?看起来不可能。

这里我检查了一下,我的调试信息版本是对的,重新在 gdb 里边运行程序直到发生段错误。错误相同。

back_color_erase 有什么特殊吗?我们现在在 ClrBlank() 中,我先列出源码:

啊,在这个函数里边没定义,难道是全局变量?

13. TUI

有必要看看这些代码在 gdb 的文本用户界面(TUI)里是什么样的,我用的不多,是看了 Greg 的演讲之后受到的启发。

你可以用 –tui 来启动:

它在抱怨没有 Python 源码。我可以搞定,但是我们是在 libncursesw 里边崩溃的。所以不管它敲回车让它完成加载,在发生错误的地方加载了 libncursesw 调试信息里的源码:

棒极了!

“>” 指向发生崩溃的那行代码。更棒的是:用 layout split 命令,我们可以在不同的窗口查看源代码和汇编代码。

Greg 演示这个的时候,和这里的顺序相反,因此你可想像同时查看源代码和汇编的情景(这里我需要一个视频来演示)。

14. 外部工具:cscope

我需要对 back_color_erase 有更多了解,我可以试试 gdb 的 搜索命令,但是我发现用一个外部工具:cscope 更快。 cscope 是一个基于文本的代码浏览器 ,诞生于80年代的贝尔实验室。如果你有喜欢的现代 IDE,可以不用它。

安装 cscope:

cscope -bqR 用来建立查找数据库。cscope -dq 用来启动 cscope。

查找 back_color_erase 的定义:

敲回车:

哦,一个宏定义。(作为宏定义的常见的形式,它们至少应该大写)

好吧,那么 CUR 是什么呢? 用 cscope 查找定义易如反掌。

起码这个宏定义是大写的!

我们通过逐条查看指令和寄存器找更早定义的 cur_term 。它是什么呢?

cscope 读取了 /usr/include/term.h 。好吧,更多的宏。我用加粗来突出这行代码, 我认为它产生了影响。为什么这里会有 “if 0 && !0 … elif 0” ?我不清楚(需要再读些代码)。有时程序员会在他们想要在产品中失效的调试代码附近使用 “#if 0”,可是,这个好像是自动生成的。

查找 NCURSES_EXPORT_VAR 发现:

… 和 NCURSES_IMPEXP:

… 还有 TERMINAL:

嗨!TERMINAL 是大写的。和宏混在一起,这个代码不太好跟踪 …

好吧,到底是谁给 cur_term 赋的值呢?记住我们的问题是它被赋值为零,也许因为它未被初始化或显式赋值。浏览给它赋值的代码路径可能会找到更多的线索,来回答为什么没被初始化,或为什么被赋值为零。使用 cscope 的第一个选项:

快速浏览项发现:

我加了高亮。甚至函数名称都被封装在宏里。但至少我们发现了 cur_term 如何被赋值的:通过 set_curterm()。也许它没被调用?

15. 外部工具:perf-tools/ftrace/uprobes

我稍后将介绍如何用 gdb 解决这个问题,可是我忍不住尝试我 perf-tools 工具箱里的 uprobe 工具,它使用 Linux 下的 ftrace 和 uprobes。用 tracers 的一个好处是它不会终止目标进程,像 gdb 一样(尽管对于这里的 cachetop.py 没什么用)。另一个好处是追踪几个和几千个进程一样容易。

我应该能追踪 libncursesw 对 set_curterm() 的调用,甚至打印出它的第一个参数:

咦,没起作用。set_curterm() 在哪?有很多方法可以找到它,比如 gdb 或 objdump:

gdb 表现的好些。此外如果仔细看源代码,我注意到它是为 libtinfo 构建的。

试着在 libtinfo 里边查找 set_curterm() :

找到了。所以 set_curterm() 被调用了,并且被调用了四次。最后一次被传了一个零,看起来这就是问题所在。

如果你觉得疑惑,我怎么就知道 %di 寄存器就是第一个参数呢,因为 AMD64/x86_64 ABI 写着呢(假设这个库和 ABI 兼容)。这里有提示:

我还想知道调用 arg1=0x0 的堆栈信息,但是 ftrace 还不支持栈追踪。

16. 外部工具:bcc/BPF

由于我们在调试 bcc 工具 cachetop.py,值得注意的是 bcc 里的 trace.py 有和我的老工具 uprobe 类似的功能:

是的,我们在用 bcc 调试 bcc !

如果你对 bcc 不熟悉,它值得一看。它为 Linux4.x 系列里的 BPF 新特性提供了 Python 和 lua 接口 。总之,它能让很多以前不可能或昂贵以致无法运行的性能工具运行起来。我以前发过贴介绍如何在 Ubuntu Xenial 上运行它。

bcc 的 trace.py 工具应该有一个开关来决定是否打印用户堆栈,因为内核从 Linux4.6 开始具备 BPF 堆栈功能,不过到写这篇文章的时候我们还没有加上这个开关。

17. 更多的断点

我真的应该从在 set_curterm() 下了断点的 gdb 入手,可是我觉得我们走的弯路,使用ftrace和BPF的还是蛮有趣的。

回到实时运行模式:

好的,在这个断点我们可以看到 set_curterm() 被调用了,被传了一个 termp = 0x0 的参数, 多亏了 debuginfo 提供的信息。如果没有 debuginfo ,我只能在每个断点处打印寄存器值。

我打印栈帧出来,这样我们可以看到是谁将 curterm 设为零的。

好了,有了更多的线索…我认为。我们在 llvm::sys::Process::FileDescriptorHasColors()里边。llvm 编译器有问题?

18. 外部工具:cscope,再来一次

代码较多的时候使用 cscope 查看,这次是 llvm。FileDescriptorHasColors() 函数:

这是较早版本中使用的代码:

用空指针调用 set_curterm() 变成了 “愚蠢的舞蹈” 。

19. 写内存

作为实验,我要修改程序内存来避免 set_curterm() 被置零,用来探索可能的解决方法。

运行 gdb ,在 set_curterm() 下断点,跑到零调用的地方:

这里我用 set 命令来改写内存,把零换成在前面看到的 set_curterm() 参数 0xbecb90 ,希望它仍是合法的。

警告:写内存不安全!gdb 不会问你 “你确定?”。如果你写错了或者敲错了,会搞坏程序。最好的情况是你的程序立即奔溃,你意识到自己做错了。最糟的情况,程序使用坏的数据继续运行几年之后被发现是错的。

这里,我在不用于生产的实验室机器上做试验,所以我继续。
我以16进制(p/x)的形式打印 %rdi 的值,然后将其设为之前的地址,再打印一次,最后打印所有寄存器的值:

(因为这里我已经安装了调试信息,因此不必使用寄存器,我可以设置传给 set_curterm() 的参数参数 “termp”,而不是 $rdi。)

现在 %rdi 被用到了,所以那些寄存器看起来还能继续用。

好的,在调用 set_curterm() 时程序没崩!但遇到另一个参数也是零的问题。我们故技重施:

啊。这就是我写内存的后果。所以这次试验以另一个段错误结束。

20. 条件断点

在前面一节,我用了 3 个 continues 到达断点的正确调用处。如果有几百次调用的话,就得用条件断点了。这里有个例子。

和之前一样我运行程序,在 set_curterm() 下断点:

现在我要将 1 号断点变成条件断点,这样它只会在 %rdi 的值为零是被触发:

漂亮!cond 是 conditional 的简写。为什么当我第一次创建 “pending” 断点的时候没有立即运行它呢?因为我发现在 pending 断点上条件不管用,至少在这个版本的 gdb 上是这样。(要么是我哪里做错了。)我也用 i b (info breakpoints)列出了断点信息。

21. 返回命令

我曾经试过另一个改值的方法,但是这次我要改指令而不是数据。

警告:看前边的警告,这里也适用。

和之前一样我们来到 set_curterm 零断点处,然后敲入 ret (return 的简写),就会立即从此函数返回并且不执行这个函数。我想用不执行函数的方式让全局变量 curterm 不被置零。

又崩了。这是我搞砸的现场。

再试一次。在多看了一点代码之后,我想第二次尝试 ret,以防父函数被卷进来。再来一次,这只是一次非常规试验:

屏幕清空暂停…然后刷新:

哇!成功了!

22. 更好的方案

我已经把调试输出发布到 github,因为 BPF 首席工程师,Alexei Starovoitov 对 llvm 也很精通,问题的根源好像是 llvm 的一个 bug。当我在用写内存和返回命令瞎搞的时候,他建议我在 bcc 加上 llvm 选项 -fno-color-diagnostics,来避免这个问题。成功了!把它加到 bcc 里是一个解决办法。(我还是希望 llvm 的 bug 能被修复)

23. Python 环境

至此问题已经解决了,但是你可能会好奇想看修复好的堆栈回溯。

安装 python-dbg:

现在我回到 gdb 来看堆栈回溯:

没有 “??” 了,但也没什么大用。

python 调试包给 gdb 加入了别的功能。现在我们可以看 python 的回溯:

… 和Python 源码:

它识别出了我们之前执行的 python 代码中的段错误。真是太棒了!

原先堆栈回溯的问题是我们看到了 python 内部在执行方法,却看不到方法本身。如果你调试别的语言,要取决于它的编译选项和运行环境,还有怎么结束执行代码。如果你在网上搜索 “语言名” 和 “gdb” 你可能会找到像 Python 一样的 gdb 扩展。如果没有的话,坏消息是你需要自己写,好消息是这样做是可行的!当它们可以用 Python 来写的时候,请搜索 “adding new GDB commands in Python” 的资料。

24. 更多命令

看起来好像我写了一个 gdb 的全面介绍,但我真的没有:gdb 里还有很多命令我没提到。help 命令列出了主要部分:

你可以对每一类命令执行 help。例如,这是 breakpoints 类的全部清单:

这些帮助表明了 gdb 有很多功能,也说明了我在示例中用到的只是一小部分。

25. 结语

好吧,这个问题有点恶心:一个 LLVM bug 破坏了 ncurses 并引起了 Python 程序的段错误。但是我用来调试的命令和步骤很常见:看堆栈,检查寄存器,下断点,逐步排查,看源码。

当我第一次使用 gdb 的时候(多年前),我真的不喜欢它。觉得它不灵活而且功能有限。从那之后 gdb 进步了很多,我也掌握了 gdb 的技巧,我现在认为它是一个强大的现代调试器。不同的调试器特性可能不同,但是 gdb 可能是目前基于文本的最强大的调试器,lldb 正奋起直追。

我希望我分享的有完整输出的 gdb 示例和我提到的不同的警告,会对搜到它的人有帮助。有机会的话我会发布更多的 gdb 示例,特别是其他运行环境比如Java。

用 q 退出 gdb。

【深度学习】普通卷积、DWconv(逐深度卷积)与PWconv(逐点卷积)以及DSconv(深度可分离卷积) 深度可分离卷积(Depthwise Separable Convolution)通过将常规卷积分解为逐通道卷积(Depthwise)和逐点卷积(Pointwise)两步,显著减少了参数量和计算成本。常规卷积同时提取空间和通道特征,而深度可分离卷积先对每个通道单独进行空间卷积,再用1×1卷积调整通道数。以输入3通道、输出4通道的64×64图像为例,常规卷积需108个参数,而深度可分离卷积仅需39个参数,减少了约2/3。这种结构在轻量级网络(如MobileNet)中广泛应用,可在保持性能的同时降低计算资源需求。 阅读详情

相关推荐

波束形成算法:LCMV实现(MATLAB)

阵列信号处理,波束成形,

weixin_43601588的博客 1万+

linux下使用core文件和gdb查找段错误的基本步骤

1. 设置环境: 1.1.设置core文件的输出目录(这里是当前目录)及文件名格式. %p是进程号 echo "./%p.core" > /proc/sys/kernel/core_pattern 1.2.设置core文件的大小 ulimit -c unlimited 1.3. 生成core文件后,用gdb打开,  exename是产生core文件的可执行文件名,

hgjyts65fg的专栏 1306

NC65实现Restful接口开发及调试

NC65实现Restful接口开发及调试

linzhongshu的专栏 2144

gdb 调试入门,大牛写的高质量指南

gdb 调试 ncurses 全过程: 发现网上的“gdb 示例”只有命令而没有对应的输出,我有点不满意。gdb 是 GNU 调试器,Linux 上的标配调试器。当我看 Greg Law 在 CppCon 2015 上的演讲《给我 15 分钟,我将改变你的对 GDB 的认知》的时候,我想起了示例输出的不足,幸运的是,这次有输出!这 15 分钟太值了。 它也启发我去分享一个完整的 gdb 调试实...

luguifang2011的专栏 1万+

手把手教你用开源EtherCAT协议栈SOEM开发从站设备(附避坑指南)

本文详细介绍了如何使用开源EtherCAT从站协议栈SOES进行嵌入式设备开发。内容涵盖从环境搭建、硬件准备到核心的对象字典与PDO映射配置,并重点分享了主循环集成、状态机处理以及实战调试中的常见问题与避坑指南,旨在帮助开发者高效实现设备接入工业现场总线网络。

linux的博客 625

NHANES更新数据后,权重计算方式也更新了

官网说明在此:如果你比我还懒,我下载了几个说明文件。2021年8月至2023年8月的总样本量与之前的2年周期相似。然而,。特别是,与之前包括过度抽样的周期相比,非西班牙裔白人的样本量较高,而非西班牙裔黑人的样本量较低。此外,60岁及以上人群的样本量较高,而年轻群体的样本量较低。子组的估计值可能具有较低的精确度,因此,检测组间差异的统计能力可能较低。此外,年龄和种族/西班牙裔亚组(尤其是儿童和青少年年龄组)的估计值可能会显示意想不到的模式。

珏世佳人的博客 2409

[转载]gdb 调试入门,大牛写的高质量指南

转自:https://blog.youkuaiyun.com/wu_cai_/article/details/79669842 ( Brendan Gregg) gdb 调试 ncurses 全过程: 发现网上的“gdb 示例”只有命令而没有对应的输出,我有点不满意。gdb 是 GNU 调试器,Linux 上的标配调试器。当我看 Greg Law 在 CppCon 2015 上的演讲《给我 15 分钟,我将改...

Kerbal's BIOG 1871

USB接口ESD防护设计实战:从金属外壳到信号线的完整避坑指南

本文深入探讨USB接口ESD防护设计的实战要点,聚焦金属外壳作为ESD能量泄放关键通道的处理策略。文章详细解析了从外壳接地路径控制、信号线TVS管选型与布局,到PCB分区及电源线滤波等完整设计流程,旨在帮助硬件工程师构建系统级防护,避免常见设计误区,确保产品通过严苛的静电测试。

k8l9m0n的博客 481

「FVWM」- FvwmButtons @20210123

FvwmButtons,FVWM的按钮盒子。可以在其中创建各种按钮,也可以”吞并“(Swallow)各种窗口。所谓吞并就是把某个程序窗口包含在FvwmButtons中。如下截图: 上面的截图中,包含了几个普通的按钮,还吞并了任务栏窗口 模块语法格式 Module FvwmButtons [-g geometry] [-transient | -transientpanel] [name [configfile]] 模块描述 FvwmButtons只能由fvwm产生,命令行调用FvwmButt.

k4nz 2165

EMC辐射发射测试:垂直与水平极化测试原理与实战指南

电磁兼容(EMC)测试是确保电子设备在复杂电磁环境中稳定运行的关键环节,其核心在于评估设备产生的电磁干扰(EMI)强度。辐射发射测试作为EMC测试的重要组成部分,通过测量设备向空间辐射的电磁噪声,判断其是否符合国际标准限值。测试原理基于电磁波的极化特性,即电场矢量的振动方向,主要分为垂直极化和水平极化。理解极化特性对于精准定位辐射源、高效进行EMC整改具有重要技术价值。在工程实践中,垂直极化噪声通常源于线缆辐射等垂直结构,而水平极化噪声多来自PCB走线等水平结构。通过分别测量两种极化方向的辐射最大值,可以全

weixin_32770423的博客 350

Win11 24H2家庭版共享打印机失败?别慌,一个批处理脚本搞定所有设置

本文提供了Win11 24H2家庭版共享打印机失败的解决方案,通过一个批处理脚本自动修复所有设置问题。脚本包含安装组策略组件、修改关键注册表项等操作,帮助用户快速恢复打印机共享功能,适用于普通家庭用户。

weixin_30632089的博客 418

XSS专题

①钓鱼页面+xss结合使用 典型 cs+xss组合拳 //① <script>alert(url)</script> //② <script src="http://192.168.56.132/pkxss/xfish/fish.php"></script> //③html注入钓鱼 <script>alert(<html><head><title>login</title></head>&

goddemon 8247

Linux 下安装 openjdk 17【详细步骤】

JDK17,安装教程。

甘蓝的专栏 7502

GDB 基础使用与多进程调试

​ GDB 全称“GNU symbolic debugger”是 Linux 下常用的程序调试器,当下的 GDB 支持调试多种编程语言编写的程序,包括 C、C++、Go、Objective-C、OpenCL、Ada 等。

王清欢的博客 1万+

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

c语言面试题大汇总

 4.    static有什么用途?(请至少说明两种)1.限制变量的作用域2.设置变量的存储域7.    引用与指针有什么区别?1) 引用必须被初始化,指针不必。2) 引用初始化以后不能被改变,指针可以改变所指的对象。2) 不存在指向空值的引用,但是存在指向空值的指针。8.    描述实时系统的基本特性在特定时间内完成特定的任务,实时性与可靠性9.    全局变量和局部变量在内存中是否有区别?如

ldhlsj的专栏 881

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

二叉树的基本概念

1.二叉树     二叉树(Binary Tree)是个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个结点。 二叉树是有序的,即若将其左、右子树颠倒,就成为另一棵不同的二叉树。即使树中结点只有一棵子树,也要区分它是左子树还是右子树。因此二叉树具有五种基本形

u010944926的专栏 2929

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

中小型架构

架构需求: 1 架构网站:zrlog wecenter wordpress cloud 2 要求: 实现两个负载均衡器代理并介入keepalived高可用 3 实现全站https加密 4 实现两个web站点 5 实现nfs服务器存储网站静态资源 6 实现backup服务器能实时有nfs同步(rersync/lsync)过来的数据 实现全网备份功能(rsync) 7 ...

xiha的博客 3244

linux解析core文件都是问号,gdb core文件函数出现问号

原创地址http://blog.youkuaiyun.com/yudingding6197/article/details/5528989我的程序crash,有了coredump文件,在Linux PC上用arm-linux-gdb debug it. The result is:#0 0x4022b178 in ?? ()(gdb) bt#0 0x4022b178 in ?? ()#1 0x4022...

weixin_36214932的博客 460

100部经典电影

1、肖申克的救赎。 ed2k://|file|Top001.èè.The.Shawshank.Redemption.1994.BDRip.2Audio.MiniSD-TLF.mkv|948042915|b6bf0c172ae1a85192fc4821b4141159|h=shrcrf2nln5nrp3k56kjbz7mkzs3amgv|/ 2、。教父1。 1392.8MB ed2k:/

黄沙百战穿金甲,不破楼兰终不还。 8万+

共享库报错问题及解决方案

报错: /lib/x86_64-linux-gnu/libtinfo.so.5: version `NCURSES_TINFO_5.0.19991023' not found (required by /lib/x86_64-linux-gnu/libbcc.so.0) 解决: sudo ln -s libncursesw.so.6 libncursesw.so.5 报错: /lib/x86_64-linux-gnu/libtinfo.so.5: version `NCURSES_TINFO_5.0.1

金荣的个人技术博客 3232

GDB调试命令详解

GDB调试命令详解GDB调试命令详解概念作用安装使用GDB单步调试查看堆栈信息调试正在执行的程序调试执行异常崩溃的程序 GDB调试命令详解 概念 通过调试程序,我们可以监控程序执行的每一个细节,包括变量的值、函数的调用过程、内存中数据、线程的调度等,从而发现隐藏的错误或者低效的代码 作用 1、程序启动时,可以按照我们自定义的要求运行程序,例如设置参数和环境变量; 2、可使被调试程序在指定代码处暂停运行,并查看当前程序的运行状态(例如当前变量的值,函数的执行结果等),即支持断点调试; 3、程序执行过程中,可以

weixin_36335122的博客 7166

gdb命令

http://www.cnblogs.com/rosesmall/archive/2012/04/10/2440514.html 一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,我们必须要  把调试信息加到可执行文件中。使用编译 器(cc/gcc/g++)的 -g 参数可以做到这一点。如:  > cc -g hello.c -o hello  >

mfcSmile的专栏 1059

GDB调试c++程序

示例文件main.cpp: #include <iostream> using namespace std; int main(int argc,char *argv[]) { cout << "hello gdb" << endl; return 0; } 目录结构:code lee@lee-PC:~/code$ tree . ├── bin ├── lib └── src └── gdb └── mian.c

Lee notes 1125

GDB Core

GDB Core 原文网址:http://blog.youkuaiyun.com/duanbeibei/article/details/6923716 程序运行发生异常退出,比如segment错误,此时可以利用系统生成的core文件,配合GDB来定位问题。 问题程序: segment.c [cpp] view plaincopy #incl

yuyantai1234的专栏 891

GDB使用的2个技巧

GDB使用的两个技巧

ld_long的博客 980

联机的Linux的系统分析(第二部分)(第一版)

联机的Linux的系统分析(第二部分)(第一版)====================================================================== ----原著:Mariusz Burdach翻译:西安邮电学院电科0101 徐兆元?? 02985384887译文版权: 徐兆元 西安邮电学院156# FLxyzsby@163.com/FLxy

FLxyzsby的专栏 2012
上一篇: TCP协议的性能评测工具 — Tcpdive开源啦
下一篇: gcc 内置函数-效率
linux_vae
博客等级 码龄15年 48粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值