院 实验报告书
课程名: 《Linux程序设计》
题 目: 实验一
Linux C编程工具:GCC和GDB
班 级: 软件131 学 号:
姓 名: 王裕
评语: 成绩: 指导教师: 批阅时间: 年 月 日 一、 实验目的与要求
1. 掌握Linux C开发过程中的基本概念; 2. 掌握如GCC,GDB等开发工具的使用。
二、 实验内容
1. 将参考代码录入到test1.c文件中,编译执行后发现结果与预期不一致,请使用
GDB调试,完成字符串反序输出功能。
三、 参考源代码
#include int reverse_str(char *string); int main (void) { char string[] = \"Linux C Tools : GCC and GDB\"; printf (\"The original string is %s \\n\ reverse_str (string); } int reverse_str (char *str) { char *new_str; int i, size; size = strlen (str); if((new_str = (char *) malloc (size + 1)) == NULL) { return -1; } for (i = 0; i < size; i++) new_str[size - i] = str[i]; new_str[size+1] = ' '; printf(\"The reversed string is %s\\n\ free(new_str); return 0 ; } 四、 实验步骤 步骤1. 编辑源代码test1.c mkdir test1 cd test1 gedit test1.c (1) 使用gedit编辑器,建议课外学习vim; (2) 分析代码中语句功能。 步骤2. 编译源代码test1.c gcc test1.c -o test1 -g (1) 复习gcc常用选项; (2) 帮助学生排查编译时错误。 (3) 分析输出结果 步骤3. 调试test1 gdb test1 (1) 回顾调试的基本方法:跟踪语句执行过程,观察执行结果; (2) 设置断点的三种基本方法: ① b ② b (3) 查看中间输出结果: ① p ② set print element 0 p 说明:GDB中查看字符串变量值可通过“set print element 0”命令,一次性显示字符串所有内容。 (4) 分析中间结果,修改28行语句为new_str[size - i-1] = str[i]; 五、 实验结果与截图 1. 编写test1.c文件并编译 2.设置断点,进行gdb测试跟踪变量。执行到i=27时size-i=0,str[27]已经超过str字符串限制,于是new_str[0]=’\\0’。 输出new_str时,由于超过限制无法输出。所以修改程序第28行语句为new_str[size - i-1] = str[i]; 正确的程序运行结果如下图所示。 六、 思考题 1. 分析以下代码,完成指定范围内数值累加功能: #include /*函数功能:将low到high之间的数值累加求和*/ int add_range(int low, int high) { int i, sum; for (i = low; i <= high; i++) sum = sum + i; return sum; } int main(void) { int result[2]; result[0] = add_range(1, 10); result[1] = add_range(1, 100); printf(\"result[0]=%d\\nresult[1]=%d\\n\ return 0; } 答:进行累加时,局部变量sum的值会被内存保存下来,会导致数值错误,要对其初始化为0。 把int i,sum;改为int i;int sum = 0; 2. 结构化编程经常将相近功能编译成库形式,方便调用。请查阅资料,使用GCC将一 组功能相关的源文件编译成静态库或动态库? 建立库文件的源文件print1.c和print2.c如下所示: /*print1.c */ #include /*print2.c */ #include 调用库函数的源文件为main.c如下: /*main.c */ void print1(int arg); void print2(char* arg); int main(int argc, char* argv[]) { int i = 3; char* str = \"test libary!\\n\"; print1(i); print2(str); return 0 ; } 生成静态库(myprint.a)并使用的基本步骤 步骤1:编译print1.c, print2.c生成print1.o, print2.o目标文件 gcc -c print1.c print2.c 步骤2:生成myprint静态库文件libmyprint.a ar -r libmyprint.a print1.o print2.o 步骤3:拷贝库文件libmyprint.a到/usr/lib目录下 sudo cp libmyprint.a /usr/lib 说明:若不将静态链接库拷贝到/usr/lib目录下,在调用该库时需通过 GCC选项-L指定库文件所在路径 步骤4:调用静态库文件,编译生成可执行二进制文件 gcc -o main main.c -lmyprint 生成动态链接库(myprint.so)并使用的基本步骤 步骤1:编译print1.c, print2.c生成print1.o, print2.o目标文件 gcc -c -fpic print1.c print2.c 注意:GCC选项“-fpic”表示独立编址,运行时可计算出相应的内部地址。 步骤2:生成myprint动态链接库libmyprint.so gcc –shared print1.o print2.o -o libmyprint.so 步骤3:拷贝库文件libmyprint.so到/usr/lib目录下 sudo cp libmyprint.so /usr/lib 步骤4:调用动态库文件,编译生成可执行二进制文件 gcc -o main main.c libmyprint.so 七、 实验体会 本次实验是Linux的第一次实验,换了一个环境,很不适应,没有鼠标操作的情况下,可以通过上下键来选择vim,gcc等操作,也极为方便了我们的操作,再有就是gdb, 语言代码除了符合最基本的语法规范之外还必须符合设计者的逻辑意图,如果发现生成的可执行文件运行结果不正确,则可以通过相应的调试环境来跟踪调试,因此需要用到gdb。比如,用来查看文件,设置断点,运行程序, 查看变量,表达式的值等等,其中的step,next等很是重要:单步执行:step、next,step 命令步入函数,而 next 命令步过函数。step up将一直执行,直至当前函数将控制返回调用它的函数为止。另外常见的gdb命令还有file,kill,list,run,quit,make等 因篇幅问题不能全部显示,请点此查看更多更全内容