用GDB调试一段简单代码

在c语言题库中看到一题:
给定程序 中函数 fun 的功能是:先将在字符串 s 中的字符按正序存放 到 t 串中,然后把 s 中的字符按逆序连接到 t 串后面。 例如:当 s 中的字符串为:“ABCDE”时,则 t 中的字符串应为:“ABCDEEDCBA”。

第一次写的代码:

#include<stdio.h>
void fun(char *s,char *t)
{
        int i = 0;
        int len = 0;
        len = sizeof(s);
        for(i = 0; i < len;i++)
        {
                t[i] = s[i];
        }
        for(i = 0; i < len; i++)
        {
                t[len + i] = s[len - i - 1];
        }
        t[2 * len] = '\0';
}
int main(void)
{
        char *a = "asdf";
        char *b = "qwer";
        fun(a,b);
        printf("%s\n",b);
        return 0;
}

运行后出现segmentation fault
进入gdb调试
gdb调试
开始以为是循环出现了问题,于是断点在第9行,run后就直接出现
gdb显示错误
突然回想起来,字符串是保存在常量区的,只可以读不可以写
于是回到原程序,修改变第二版:

#include<stdio.h>
void fun(char *s,char *t)
{
        int i = 0;
        int len = 0;
        len = sizeof(s);
        for(i = 0; i < len;i++)
        {
                t[i] = s[i];
        }
        for(i = 0; i < len; i++)
        {
                t[len + i] = s[len - i - 1];
        }
        t[2 * len] = '\0';
}
int main(void)
{
        char a[10] = "asdf";
        char b[10] = "qwer";
        fun(a,b);
        printf("%s\n",b);
        return 0;
}

将字符串保存在数组里面,数组保存在栈区里(普通数组在栈区,由malloc分配空间的数组放在堆区),是可读可写的,于是修改后运行:
再次运行程序
再次运行还是出错,有输出为“asdf”,但是目标输出是“asdffdsa”,而且出现错误,说stack smashing detected(检测到栈区被粉碎)
于是用gdb调试一下,同样是把断点放在第九行,run后:
再次gdb调试
发现,字符创存储的地址变成栈区的空间,说明字符串存储地方应该没问题,于是无数次next后:
发现第一个for循环走了8遍…本来按照传进去的字符串(“asdf”)长度应该是4,所以for循环应该走4遍才对,现在走了8遍说明,sizeof(s)得到的不是字符串长度,而是s这个字符指针的长度,走完第一个循环后 t = “asdf0000” ,所以在进入第二个for循环(倒序相接)时,字符串 t 还是第一遍循环的值,并且值已经变成“asdf 0000 0000 fdsa”,此时整个字符串的长度已经远远超过分配的内存空间了,所以栈被粉碎了

于是继续修改,存储字符串的数组由10扩增到32:

#include<stdio.h>
void fun(char *s,char *t)
{
        int i = 0;
        int len = 0;
        len = sizeof(s);
        for(i = 0; i < len;i++)
        {
                t[i] = s[i];
        }
        for(i = 0; i < len; i++)
        {
                t[len + i] = s[len - i - 1];
        }
        t[2 * len] = '\0';
}
int main(void)
{
        char a[32] = "asdf";
        char b[32] = "qwer";
        fun(a,b);
        printf("%s\n",b);
        return 0;
}

再运行程序:
运行程序
虽然有输出,但是没有达到题目的要求,题目要求的是输出后变成“asdffdsa”
再次使用gdb看看:
依旧是各自循环了8次
gdb调试
此时输出的值是“asdf”,是因为printf遇到\0就清除缓冲区,直接输出了,所以没有打印后面的字符串,所以问题是出现在sizeof这里,需要的是字符串长度,于是使用strlen:

#include<stdio.h>
#include<string.h>
void fun(char *s,char *t)
{
        int i = 0;
        int len = 0;
        len = strlen(s);
        for(i = 0; i < len;i++)
        {
                t[i] = s[i];
        }
        for(i = 0; i < len; i++)
        {
                t[len + i] = s[len - i - 1];
        }
        t[2 * len] = '\0';
}
int main(void)
{
        char a[32] = "asdf";
        char b[32] = "qwer";
        fun(a,b);
        printf("%s\n",b);
        return 0;
} 

运行程序:
程序运行
实现了题目要求的效果

需要注意的点:
1、字符串的存储地方
2、sizeof和strlen的区别
3、printf如何打印输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值