1、gcc编译
-c:只生成目标文件,但不进行连接,用于对源文件分别进行编译。 -S:只进行编译,不进行汇编。 -o: 将输出文件存放在何处,默认为./a.out -g:在编译c文件时加入供程序gdb调试的附加信息 -v:打印编译驱动版本号
需要执行main函数需要编译两个.c文件,再链接到一起执行。 操作如下
gcc -c mfile.c sq.c
gcc mfile.o sq.o -o Main
./Main
2、gdb调试
c语言中出现的有编译错误,运行错误,逻辑错误三种,前两种可以通过最初的gcc命令就可以检测到。当出逻辑错误的时候,一种是直接查看源代码进行debug,或者通过gdb调试工具查看一些变量地址是否越界,变量内容是否正确等查找错误原因,当然,错误的类型千百万,具体怎样解决问题,还要具体情况具体分析。 具体案例,地址越界
demo.c文件代码
#include<stdio.h>
#include<stdlib.h>
#define BIGNUM 20
void index_m(int ary[], float fary[]);
int main()
{
int intary[10];
float fltary[10];
index_m(intary,fltary);
return 0;
}
void index_m(int ary[], float fary[]){
int i;
float f = 3.14;
for(int i = 0; i < BIGNUM; i++){
ary[i] = i;
fary[i] = i*f;
}
}
gcc -g demo.c -o dbme
./dbme
下面使用gdb工具对程序调试,通过观察源代码大概就知道是index_m函数中数组越界了,那么我们需要查看两个数组的内容和两个数组的地址。
gdb dbme
输入
list 1, 25
在第21行设置断点。
break 21
再次运行程序
r
再次运行程序,程序会在第21行停止下来,此时对数组ary,fary的操作已经完成了,我们来看一下两个数组的内容和地址信息。 打印ary数组首地址,ary[0], ary数组所有内容
首地址
(gdb) p ary
$1 = (int *) 0x7fffffffde20
(gdb) p &ary[0]
$2 = (int *) 0x7fffffffde20
ary[0]与ary所有内容
(gdb) p ary[0]
$4 = 0
(gdb) p ary[0]@20
$3 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
查看ary[12]与fary[0]的的地址信息
(gdb) p &ary[12]
$5 = (int *) 0x7fffffffde50
(gdb) p &fary[0]
$6 = (float *) 0x7fffffffde50
这里发现ary[12]的地址与fary[0]的地址相重叠了,也就是说从ary[12]到ary[19]内容都将fary[0]到fary[8]的地址覆盖了。我们再查看fary的所有内容看看。
(gdb) p fary[0]@20
$7 = {1.68155816e-44, 1.821688e-44, 1.96181785e-44, 2.1019477e-44, 2.24207754e-44,
2.38220739e-44, 2.52233724e-44, 2.66246708e-44, 25.1200008, 28.2600002, 31.4000015,
34.5400009, 37.6800003, 40.8199997, 43.9600029, 47.1000023, 50.2400017, 53.3800011,
56.5200005, 59.6600037}
能够看到fary前8个内容是出现错误。说明在index_m函数中for循环的上界可能存在问题,20的确是超过了定义数组时10的上界。
|