了解更多有关gdb的内容
GNU调试器是一个强大的工具,可以提供大量的有关运行程序内部状态的信息。在支持一个名叫硬件断点(hardware breakpoint)的实用程序的系统上,我们可以使用gdb来实时的查看变量的改变。硬件断点是某些CPU的一个特性;如果出现特定的条件,通常是在指定区域的内存访问,这些处理器能够自动停止。相对应的,gdb可以使用watch表达式。这就意味着,出于性能考虑,当一个表达式具有一个特定的值时,gdb可以停止这个程序,而不论计算发生在程序中的哪个位置。
断点可以使用计数以及条件进行设置,从而他们只在一定的次数之后或是当满足一个条件时才会被引发。
gdb也能够将其本身附在已经运行的程序中。这对于我们调试客户端/服务器系统时是非常有用的,因为我们可以调试一个正在运行的行为不当的服务器进程,而不需要停止与重启服务器。例如,我们可以使用gcc -O -g选项来编译我们的程序,从而得到优化与调试的好处。不足之处就是优化也许会重新组织代码,所以当我们分步执行时,我们也许会发出我们自身的跳转来达到与原始源代码相同的效果。
我们也可以使用gdb来调试已经崩溃的程序。Linux与Unix经常会在一个程序失败时在一个名为core的文件中生成一个核心转储信息。这是一个程序内存的图象并且会包含失败时全局变量的值。我们可以使用gdb来查看当程序崩溃时程序运行到哪里。查看gdb手册页我们可以得到更为详细的信息。
gdb以GPL许可证发布并且绝大多数的Unix系统都会支持他。我们强烈建议了解gdb。
更多的调试工具
除了强大的调试工具,例如gdb,Linux系统通常还会提供一些其他们的我们可以用于诊治调试进程的工具。其中的一些会提供关于一个程序的静态信息;其他的会提供动态分析。
静态分析只由程序源代码提供信息。例如ctags,cxref,与cflow这样的程序与源代码一同工作,并且会提供有关函数调用与位置的有用信息。
动态会析会提供有关一个程序在执行过程中如何动作的信息。例如prof与gprof这样的程序会提供有关执行了哪个函数并且执行多长时间的信息。
下面我们来看一下其中的一些工具及其输出。并不是所有的这些工具都可以在所有的系统上得到,尽管其中的一些都有自由版本。
Lint:由我们的程序中移除Fluff
原始的Unix系统提供了一个名为lint的实用程序。他实质是一个C编译的前端,带有一个测试设计来适应一些常识并且生成警告。他会检测变量在设计之前在哪里使用以及哪里函数参数没有被使用,以及其他的一些情况。
更为现代的C编译器可以编译性能为代价提供类似的警告。lint本身已经被C标准所超越。因为这个工具是基于早期的C编译器,他并不能处理所有的ANSI语法。有一些商业版本的lint可以用于Unix,而且在网络上至少有一个名为splint可以用于Linux。这就是过去所知的LClint,他是MIT一个工程的一部分,来生成用于通常规范的工具。一个类似于lint的工具splint可以提供查看注释的有用代码。splint可以在htt://www.splin.org处得到。
下面是一个编辑过的splint例子输出,这是运行我们在前面调试的例子程序的早期版本中所产生的输出:
neil@beast:~/BLP3/chapter10> splint -strict debug0.c
Splint 3.0.1.6 --- 27 Mar 2002
debug0.c:14:22: Old style function declaration
Function definition is in old style syntax. Standard prototype syntax is
preferred. (Use -oldstyle to inhibit warning)
debug0.c: (in function sort)
debug0.c:20:31: Variable s used before definition
An rvalue is used that may not be initialized to a value on some execution
path. (Use -usedef to inhibit warning)
debug0.c:20:23: Left operand of & is not unsigned value (boolean):
i < n & s != 0
An operand to a bitwise operator is not an unsigned values. This may have
unexpected results depending on the signed representations. (Use
-bitwisesigned to inhibit warning)
debug0.c:20:23: Test expression for for not boolean, type unsigned int:
i < n & s != 0
Test expression type is not boolean or int. (Use -predboolint to inhibit
warning)
debug0.c:20:23: Operands of & are non-integer (boolean) (in post loop test):
i < n & s != 0
A primitive operation does not type check strictly. (Use -strictops to
inhibit warning)
debug0.c:32:14: Path with no return in function declared to return int
There is a path through a function declared to return a value on which there
is no return statement. This means the execution may fall through without
returning a meaningful result to the caller. (Use -noret to inhibit warning)
debug0.c:34:13: Function main declared without parameter list
A function declaration does not have a parameter list. (Use -noparams to
inhibit warning)
debug0.c: (in function main)
debug0.c:36:17: Return value (type int) ignored: sort(array, 5)
Result returned by function call is not used. If this is intended, can cast
result to (void) to eliminate message. (Use -retvalint to inhibit warning)
debug0.c:37:14: Path with no return in function declared to return int
debug0.c:14:13: Function exported but not used outside debug0: sort
debug0.c:15:17: Definition of sort
Finished checking --- 22 code warnings
$
这个程序报告旧风格的函数定义以及函数返回类型与他们实际返回类型之间的不一致。这些并不会影响程序的操作,但是应该注意。
他还在下面的代码片段中检测到两个实在的bug:
/* 18 */ int s;
/* 19 */
/* 20 */ for(; i < n & s != 0; i++) {
/* 21 */ s = 0;
splint已经确定在20行使用了变量s,但是并没有进行初始化,而且操作符&已经被更为通常的&&所替代。在这个例子中,操作符优先级修改了测试的意义并且是程序的一个问题。
所有这些错误都在调试开始之前在代码查看中被修正。尽管这个例子有一个故意演示的目的,但是这些错误真实世界的程序中经常会出现的。
函数调用工具
三个实用程序-ctags,cxref与cflow-形成了X/Open规范的部分,所以必须在具有软件开发功能的Unix分枝系统上提供。
ctags
ctags程序创建函数索引。对于每一个函数,我们都会得到一个他在何处使用的列表,与书的索引类似。
ctags [-a] [-f filename] sourcefile sourcefile ...
ctags -x sourcefile sourcefile ...
默认情况下,ctags在当前目录下创建一个名为tags的目录,其中包括在输入源文件码中所声明的每一个函数,如下面的格式
announce app_ui.c /^static void announce(void) /
文件中的每一行由一个函数名,其声明所在的文件,以及一个可以用在文件中查找到函数定义所用的正则表达式所组成。一些编辑器,例如Emacs可以使用这种类型的文件在源码中遍历。
相对应的,通过使用ctags的-x选项,我们可以在标准输出上产生类似格式的输出:
find_cat 403 app_ui.c static cdc_entry find_cat(
我们可以通过使用-f filename选项将输出重定向到另一个不同的文件中,或是通过指定-a选项将其添加到一个已经存在的文件中。
cxref
cxref程序分析C源代码并且生成一个交叉引用。他显示了每一个符号在程序中何处被提到。他使用标记星号的每一个符号定义位置生成一个排序列表,如下所示:
SYMBOL FILE FUNCTION LINE
BASENID prog.c — *12 *96 124 126 146 156 166
BINSIZE prog.c — *30 197 198 199 206
BUFMAX prog.c — *44 45 90
BUFSIZ /usr/include/stdio.h — *4
EOF /usr/include/stdio.h — *27
argc prog.c — 36
prog.c main *37 61 81
argv prog.c — 36
prog.c main *38 61
calldata prog.c — *5
prog.c main 64 188
calls prog.c — *19
prog.c main 54
在作者的机子上,前面的输入在程序的源码目录中使用下面的命令来生成的:
$ cxref *.c *.h
但是实际的语法因为版本的不同而不同。查看我们系统的文档或是man手册可以得到更多的信息。
cflow
cflow程序会输出一个函数调用树,这是一个显示函数调用关系的图表。这对于查看程序结构来了解他是如何操作的以及了解对于一个函数有哪些影响是十分有用的。一些版本的cflow可以同时作用于目标文件与源代码。查看手册页我们可以了解更为详细的操作。
下面是由一个cflow版本(cflow-2.0)所获得的例子输出,这个版本的cflow版本是由Marty Leisner维护的,并且可以网上得到。
1 file_ungetc {prcc.c 997}
2 main {prcc.c 70}
3 getopt {}
4 show_all_lists {prcc.c 1070}
5 display_list {prcc.c 1056}
6 printf {}
7 exit {}
8 exit {}
9 usage {prcc.c 59}
10 fprintf {}
11 exit {}
从这个输出中我们可以看到main函数调用show_all_lists,而show_all_lists调用display_list,display_list本身调用printf。
这个版本cflow的一个选项就是-i,这会生成一个反转的流程图。对于每一个函数,cflow列出调用他的其他函数。这听起来有些复杂,但是实际上并不是这样。下面是一个例子。
19 display_list {prcc.c 1056}
20 show_all_lists {prcc.c 1070}
21 exit {}
22 main {prcc.c 70}
23 show_all_lists {prcc.c 1070}
24 usage {prcc.c 59}
...
74 printf {}
75 display_list {prcc.c 1056}
76 maketag {prcc.c 487}
77 show_all_lists {prcc.c 1070}
78 main {prcc.c 70}
...
99 usage {prcc.c 59}
100 main {prcc.c 70}
例如,这告诉我们调用exit的函数有main,show_all_lists与usage。
使用prof/gprof执行性能测试
当我们试着追踪一个程序的性能问题时一个十分有用的技术就是执行性能测试(execution profiling)。通常被特殊的编译器选项以及辅助程序所支持,一个程序的性能显示他在哪里花费时间。
prof程序(以及其GNU版本gprof)会由性能测试程序运行时所生成的执行追踪文件中输出报告。一个可执行的性能测试是由指定-p选项(对prof)或是-pg选项(对gprof)所生成的:
$ cc -pg -o program program.c
这个程序是使用一个特殊版本的C库进行链接的并且被修改来包含监视代码。对于不同的系统结果也许不同,但是通常是由安排频繁被中断的程序以及记录执行位置来做到的。监视数据被写入当前目录中的一个文件,mon.out(对于gprof为gmon.out)。
$ ./program
$ ls -ls
2 -rw-r--r-- 1 neil users 1294 Feb 4 11:48 gmon.out
prof/gprof程序读取这些监视数据并且生成一个报告。查看其手册页可以详细了解其程序选项。下面以gprof输出作为一个例子:
cumulative self self total
time seconds seconds calls ms/call ms/call name
18.5 0.10 0.10 8664 0.01 0.03 _doscan [4]
18.5 0.20 0.10 mcount (60)
14.8 0.28 0.08 43320 0.00 0.00 _number [5]
9.3 0.33 0.05 8664 0.01 0.01 _format_arg [6]
7.4 0.37 0.04 112632 0.00 0.00 _ungetc [8]
7.4 0.41 0.04 8757 0.00 0.00 _memccpy [9]
7.4 0.45 0.04 1 40.00 390.02 _main [2]
3.7 0.47 0.02 53 0.38 0.38 _read [12]
3.7 0.49 0.02 w4str [10]
1.9 0.50 0.01 26034 0.00 0.00 _strlen [16]
1.9 0.51 0.01 8664 0.00 0.00 strncmp [17]
断言
在程序的开发过程中,通常使用条件编译的方法引入调试代码,例如printf,但是在一个发布的系统中保留这些信息是不实际的。然而,经常的情况是问题出现与不正确的假设相关的程序操作过程中,而不是代码错误。这些都是"不会发生"的事件。例如,一个函数也许是在认为其输入参数总是在一定范围下而编写的。如果给他传递一些不正确的数据,也许整个系统就会崩溃。
对于这些情况,系统的内部逻辑在哪里需要验证,X/Open提供了assert宏,可以用来测试一个假设是否正确,如果不正确则会停止程序。
#include <assert.h>
void assert(int expression)
assert宏会计算表达式的值,如果不为零,则会向标准错误上输出一些诊断信息,并且调用abort来结束程序。
头文件assert.h依据NDEBUG的定义来定义宏。如果头文件被处理时定义了NDEBUG,assert实质上被定义为空。这就意味着我们可以通过使用-DNDEBUG在编译时关闭断言或是在包含assert.h文件之前包含下面这行:
#define NDEBUG
这种方法的使用是assert的一个问题。如果我们在测试中使用assert,但是却对生产代码而关闭,比起我们测试时的代码,我们的生产代码就不会太安全。在生产代码中保留断言开启状态并不是通常的选择,我们希望我们的代码向用户显示一条不友好的错误assert failed与一个停止的程序吗?我们也许会认为最好是编写我们自己的检测断言的错误追踪例程,而不必在我们的生产代码中完全禁止。
我们同时要小心在assert断言没有临界效果。例如,如果我们在一个临界效果中调用一个函数,如果移除了断言,在生产代码中就不会出现这个效果。
试验--assert
下面的程序assert.c定义了一个必须传递正值参数的函数。通过使用一个断言可以避免不正常参数的可能。
在包含assert.h头文件和检测参数是否为正的平方根函数之后,我们可以编写如下的函数:
#include <stdio.h>
#include <math.h>
#include <assert.h>
double my_sqrt(double x)
{
assert(x >= 0.0);
return sqrt(x);
}
int main()
{
printf(“sqrt +2 = %g\n”, my_sqrt(2.0));
printf(“sqrt -2 = %g\n”, my_sqrt(-2.0));
exit(0);
}
当我们运行这个程序时,我们就会看到当我们传递一个非法值时就会违背这个断言。事实上的断言失败的消息格式会因系统的不同而不同。
$ cc -o assert assert.c -lm
$ ./assert
sqrt +2 = 1.41421
assert: assert.c:7: my_sqrt: Assertion `x >= 0.0’ failed.
Aborted
$
工作原理
当我们试着使用一个负数来调用函数my_sqrt时,断言就会失败。assert宏会提供违背断言的文件和行号,以及失败的条件。程序以一个退出陷井结束。这是assert调用abort的结果。
如果我们使用-DNDEBUG选项来编译这个程序,断言就会被编译在外,而当我们由my_sqrt中调用sqrt函数时我们就会得到一个算术错误。
$ cc -o assert -DNDEBUG assert.c -lm
$ ./assert
sqrt +2 = 1.41421
Floating point exception
$
一些最近的算术库版本会返回一个NaN(Not a Number)值来表示一个不可用的结果。
sqrt –2 = nan
内存调试
富含bug而且难于跟踪调试的一个区域就是动态内存分配。如果我们编译一个使用malloc与free来分配内存的程序,很重要的一点就是我们要跟踪我们所分配的内存块,并且保证不要使用已经释放的内存块。
通常,内存是由malloc分配并且赋给一个指针变量的。如果指针变量被修改了,而又没有其他的指针来指向这个内存块,他就会变为不可访问的内存块。这就是一个内存泄露,而且会使得我们程序尺寸变大。如果我们泄露了大量的内存,那么我们的系统就会变慢并且会最终用尽内存。
如果我们在超出一个分配的内存块的结束部分(或是在一个内存块的开始部分)写入数据,我们很有可能会破坏malloc库来跟踪分配所用的数据结构。在这种情况下,在将来的某个时刻,调用malloc,或者甚至是free,就会引起段错误,而我们的程序就会崩溃。跟踪错误发生的精确点是非常困难的,因为很可能他在引起崩溃的事件发生以前很一段时间就已经发生了。
不必奇怪的是,有一些工具,商业或是自由的,可以有助于处理这两种问题类型。例如,有许多不同的malloc与free版本,其中的一些包含额外的代码在分配与回收上进行检测尝试检测一个内存块被释放两次或是其他一些滥用类型的情况。
ElectricFence
ElectricFence库是由Bruce Perens开发的,并且在一些Linux发行版本中作为一个可选的组件来提供,例如RedHat,而且已经可以在网络上获得。他尝试使用Linux的虚拟内存工具来保护malloc与free所使用的内存,从而在内存被破坏时终止程序。
试验--ElectricFence
下面的程序,efence.c,使用malloc分配一个内存块,然后在超出块结束处写入数据。让我们看一下会发生什么情况。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr = (char *) malloc(1024);
ptr[0] = 0;
/* Now write beyond the block */
ptr[1024] = 0;
exit(0);
}
当我们编译运行这个程序时,我们并不会看到进一步的行为。然而,似乎malloc所分配的内存区域有一些问题,而我们实际上已经遇到了麻烦。
$ cc -o efence efence.c
$ ./efence
$
然而,如果我们使用ElectricFence库,libefence.a来链接这个程序,我们就会得到一个即时的响应。
$ cc -o efence efence.c -lefence
$ ./efence
Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
Segmentation fault
$
在调试器下运行可以定位这个问题:
$ cc -g -o efence efence.c -lefence
$ gdb efence
(gdb) run
Starting program: /home/neil/BLP3/chapter10/efence
[New Thread 1024 (LWP 1869)]
Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1024 (LWP 1869)]
0x080484ad in main () at efence.c:10
10 ptr[1024] = 0;
(gdb)
工作原理
Electric替换malloc并且将函数与计算机处理器的虚拟内存特性相关联来阻止非法的内存访问。当这样的访问发生时,就会抛出一个段错误信息从而可以终止程序。
valgrind
valgrind是一个可以检测我们已经讨论过的许多问题的工具。事实上,他可以检测数据访问错误与内存泄露。也许他并没有被包含在我们的Linux发行版本中,但是我们可以在http://developer.kde.org/~sewardj处得到。
程序并不需要使用valgrind重新编译,而我们甚至可以调用一个正在运行的程序的内存访问。他很值得一看,他已经用在主要的开发上,包含KDE版本3。
试验--valgrind
下面的程序,checker.c,分配一些内存,读取超过那块内存限制的位置,在其结束处之外写入数据,然后使其不能访问。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr = (char *) malloc(1024);
char ch;
/* Uninitialized read */
ch = ptr[1024];
/* Write beyond the block */
ptr[1024] = 0;
/* Orphan the block */
ptr = 0;
exit(0);
}
要使用valgrind,我们只需要简单的运行valgrind命令,传递我们希望检测的选项,其后是使用其参数运行的程序。
当我们使用valgrind来运行我们的程序时,我们可以看到诊断出许多问题:
$ valgrind --leak-check=yes -v ./checker
==3436== valgrind-1.0.4, a memory error detector for x86 GNU/Linux.
==3436== Copyright (C) 2000-2002, and GNU GPL’d, by Julian Seward.
==3436== Estimated CPU clock rate is 452 MHz
==3436== For more details, rerun with: -v
==3436==
==3436== Invalid read of size 1
==3436== at 0x8048397: main (checker.c:10)
==3436== by 0x402574F2: __libc_start_main (in /lib/libc.so.6)
==3436== by 0x80482D1: exit@@GLIBC_2.0 (in /home/neil/BLP3/chapter10/checker)
==3436== Address 0x42AD1424 is 0 bytes after a block of size 1024 alloc’d
==3436== at 0x4003CA75: malloc (vg_clientfuncs.c:100)
==3436== by 0x8048389: main (checker.c:6)
==3436== by 0x402574F2: __libc_start_main (in /lib/libc.so.6)
==3436== by 0x80482D1: exit@@GLIBC_2.0 (in /home/neil/BLP3/chapter10/checker)
==3436==
==3436== Invalid write of size 1
==3436== at 0x80483A4: main (checker.c:13)
==3436== by 0x402574F2: __libc_start_main (in /lib/libc.so.6)
==3436== by 0x80482D1: exit@@GLIBC_2.0 (in /home/neil/BLP3/chapter10/checker)
==3436== Address 0x42AD1424 is 0 bytes after a block of size 1024 alloc’d
==3436== at 0x4003CA75: malloc (vg_clientfuncs.c:100)
==3436== by 0x8048389: main (checker.c:6)
==3436== by 0x402574F2: __libc_start_main (in /lib/libc.so.6)
==3436== by 0x80482D1: exit@@GLIBC_2.0 (in /home/neil/BLP3/chapter10/checker)
==3436==
==3436== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==3436== malloc/free: in use at exit: 1024 bytes in 1 blocks.
==3436== malloc/free: 1 allocs, 0 frees, 1024 bytes allocated.
==3436== For counts of detected errors, rerun with: -v
==3436== searching for pointers to 1 not-freed blocks.
==3436== checked 3468724 bytes.
==3436==
==3436== definitely lost: 1024 bytes in 1 blocks.
==3436== possibly lost: 0 bytes in 0 blocks.
==3436== still reachable: 0 bytes in 0 blocks.
==3436==
==3436== 1024 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3436== at 0x4003CA75: malloc (vg_clientfuncs.c:100)
==3436== by 0x8048389: main (checker.c:6)
==3436== by 0x402574F2: __libc_start_main (in /lib/libc.so.6)
==3436== by 0x80482D1: exit@@GLIBC_2.0 (in /home/neil/BLP3/chapter10/checker)
==3436==
==3436== LEAK SUMMARY:
==3436== definitely lost: 1024 bytes in 1 blocks.
==3436== possibly lost: 0 bytes in 0 blocks.
==3436== still reachable: 0 bytes in 0 blocks.
==3436== Reachable blocks (those to which a pointer was found) are not shown.
==3436== To see them, rerun with: --show-reachable=yes
==3436== $
这里我们可以看到错误的读取与写入已经被捕获,而所关注的内存块与他们被分配的位置相关联。我们可以使用调试器在出错点断开程序。
valgrind有许多选项,包含特定的错误类型表达式与内存泄露检测。要检测我们的例子泄露,我们必须使用一个传递给valgrind的选项。当程序结束时要检测内存泄露,我们需要指定 --leak-check=yes。我们可以使用valgrind --help得到一个选项列表。
工作原理
我们的程序在valgrind的控制下执行,这会检测我们程序所执行的各种动作,并且执行许多检测,包括内存访问。如果程序访问一个已分配的内存块并且访问是非法的,valgrind就会输出一条信息。在程序结束时,一个垃圾收集例程就会运行来检测是否在存在分配的内存块没有被释放。这些孤儿内存也会被报告。
小结
在这一章,我们了解了一些调试工具与技术。Linux提供了一些强大的工具可以用于由程序中移除缺陷。我们使用gdb来消除程序中的bug,并且了解了如cflow与splint这样的数据分析工具。最后我们了解了当我们使用动态分配内存时会出现的问题,以及一些用于类似问题诊断的工具,例如ElectricFence与valgrind。
分享到:
相关推荐
四核手机意味着手机拥有四个处理器核心,能够在处理多任务时提供更好的性能。因此,对于开发人员来说,能够调试四核处理器的手机至关重要,这能够确保软件能够充分利用硬件的处理能力,同时在出现问题时能够快速定位...
本篇文章将详细解析标题和描述中提到的四个工具:TCP UDP协议测试工具、TCPUDPDbg、TCP-UDP服务管理 V3.01以及网络调试助手NetAssis,以及它们如何帮助我们进行网络调试。 首先,TCP UDP协议测试工具是一款实用的...
在IT行业中,"速锐四向车调试工具多倍通"是一个特定的软件或插件,主要用于调试四向车(也称为AGV,Automated Guided Vehicle)的控制系统。四向车是一种能够在四个方向上自由行驶的自动化运输设备,常见于仓库、...
《四信模块调试工具详解与应用》 在IT行业中,无线通信模块的调试是一项至关重要的工作,尤其是在ZIGBEE网络构建中。四信模块调试工具正是为了解决这一问题而设计的专业软件,它极大地简化了配对调试过程,使得现场...
四、教学方法 课程教学方法主要包括: 1. 讲授法 2. 现场教学法 3. 项目任务驱动法 4. 小组讨论法 五、考核方式 课程考核方式主要包括: 1. 过程考核 2. 终结考核 3. 公司考核 4. 校内项目考核 六、结语 ...
调试的一般工艺程序包括通电前的检查、通电调试、静态调试和动态调试四个阶段。通电前的检查是指检查电源的正、负极是否接反、地线是否接触可靠、元器件、导线安装是否正确等。通电调试是指将电源正确地接入被调电路...
- 设立了汽机安装、锅炉安装、电缆敷设接线、单体调试四个施工班组,每个班组都有明确的责任分工,确保施工质量。 - 各班组的任务包括汽轮发电机、锅炉系统、电缆敷设、仪表设备的单体调试等工作。 - 电缆敷设...
在调试技术流程方面,可以从准备工作、单体调试、单回路调试、综合调试四个角度进行分析。 准备工作:在电气设备调试之前,需要做好充足的准备工作,包括熟悉设备图纸、测试设备的校验、安全防护措施的制定等。 ...
自动化调试技术主要包括硬件配置、软件编程、系统集成和现场调试四个环节。硬件配置涉及选择合适的控制器、传感器、执行机构等设备;软件编程则包括编写控制逻辑,实现设备的自动化运行;系统集成是将各个硬件和软件...
这里提到的"四个串口调试程序"提供了方便的工具来帮助开发者测试和调试串口通信。 1. **TKS_COM**:这可能是一款串口通信软件,用于监控和发送数据。这类工具通常具备打开、关闭串口,设置波特率、数据位、停止位、...
- 管理架构:设立锅炉安装、主厂房安装、电缆敷设接线、单体调试四个施工班组,每个班组有明确的责任分工。 - 技术人员要求:电缆敷设接线班由有经验的熟练人员组成,以确保工艺质量和DCS系统的接线质量。 - 工程...
四、Virtual Platform Virtual Platform 是一种仿真调试方法,也不需要目标硬件支持。Virtual Platform 可以模拟整个系统的行为,从而实现调试的目的。 Microblaze 调试方法有多种选择,开发者可以根据自己的需求...
四、其他调试内容 除了主轴和编码器调试,828D系统还涉及到PLC逻辑调试、I/O接口检查、网络配置等多方面的内容。用户应根据手册提供的指导,逐一进行细致的检查和设定,确保所有环节都能协同工作。 综上所述,...
四、使用串口调试助手 打开串口调试助手,选择COM4,设置波特率为4800,无校验位、8位数据位、1位停止位。打开COM4,串口调试助手就可以实时显示串口接收和发送的数据。 五、调试串口发送接收程序 现在,可以开始...
四、汽车燃气系统调试的重要性 汽车燃气系统的调试是保证其安全、高效运行的关键环节。不准确的参数设定可能导致燃烧不充分,增加排放,甚至损坏发动机。此外,良好的调试还可以提升燃油经济性,降低运营成本。AC...
四、安装APK 1. 将待安装的APK文件放在与ADB同一目录下,例如:“`C:\adb\myapp.apk`”。 2. 在命令提示符中输入`adb install myapp.apk`,等待安装完成。如果出现"Success",则表示安装成功。 五、无线调试ADB 1. ...
赋安消防主机调试软件包含了四个主要版本:V1.2.2、V1.3.3、V4.5以及5050-1.02。每个版本都代表了软件在不同阶段的发展与优化,以适应不断升级的消防系统需求。 - V1.2.2和V1.3.3:这两个早期版本着重于基础功能的...
四、使用技巧 1. **智能提示**:利用助手的智能提示功能,可以快速找到可能出错的代码行。 2. **多线程调试**:对于多线程程序,学会如何切换线程视图,理解各线程间的交互。 3. **内存分析**:监控内存使用情况,...
四 引发bug并打印信息 1 BUG()和BUG_ON() 2 dump_stack() 五 printk() 1 printk函数的健壮性 2 printk函数脆弱之处 3 LOG等级 4 记录缓冲区 5 syslogd/klogd 6 dmesg 7 注意 8 内核printk和日志系统的总体结构 9 ...
调试界面中有四个地方需要注意: * 最上面的调试工具栏,那有进行跟踪调试的命令按钮。 * 最左边的黄色箭头和这一灰色列,黄色箭头告诉我们现在程序运行到那一步了。 * 右边解决方案资源管理器是IIS服务器加载的ASP...