指针越界(gdb调试)。

昨天在写一段转换函数,遇到需要将一个字符串转换为另一个。在测试时,发现一个内存泄露的问题。
函数如下:
void  Str2Str(void * des, void * src)
{
    unsigned char *pDes = (unsigned char *)des;
    unsigned char *pSrc = (unsigned char *)src;
    unsigned char au8Int[4]  = {0};
    unsigned char u8Idx = 0;
    
    if(dis == NULL || src == NULL)
        return;

    while(*pSrc != '\0')
    {
        while((*pSrc != '.') && (*pSrc != '\0'))
        {
            au8Int[u8Idx] = au8Int[u8Idx] * 10 + (*pSrc & 0x0f);
            src++;
        }
        u8Idx++;
        pSrc++;
    }

    sprintf(pDes, "%d.%d.%d.%d", au8Int[0], au8Int[1], au8Int[2], au8Int[3]);
}
运行完函数后,发现没有返回值。感觉哪里不对,于是使用gdb调试了一下,发现当程序运行到sprintf()语句时,pDes与des的值竟然不一致。按照指针传递理解,这里也是直接赋值,他们应该是一致的才对。但是确实不一致。也就是这样,这个sprintf()把值写到了其他地址中,以至于传入的指针指向的地址没有数据写入,没有带回数据。

发现这个问题后,一直想不通,为什么会这样。当时还没有想到是内存溢出的问题。只知道,在后来的语句中,pDes的值发生了变化。

今天在和同事聊起来的时候,同事也想不明白。这种情况是不应该的。后来在提到,经过一个while后pDes的值发生了变化。同事提到会不会是在while()处内存泄露,导致里边的值发生了变化。这个提醒,点醒了我。

之后,把while()部分去掉,在测试,发现有值。虽然都是零,但是证明了问题确实出在这里。
然后检查这段代码,发现在内层while()退出后,pSrc又加了一次,这个造成了pSrc指向的地址越过了字符串的结尾,指向了未知的内存空间,而那个地方恰好有值,就造成了外层while()没有退出,一直再循环。于是pSrc访问的内存,超过了字符串的内存。同时,由于u8Idx也加1,造成了au8Int[]越界访问,指向了&pDes所在的内存,所以pDes的内容也因为此遭到修改。
(gdb) p &pDes
$2 = (unsigned char **) 0xbffff414
(gdb) p &au8Int
$4 = (unsigned char (*)[4]) 0xbffff410
(gdb) p &au8Int[4]
$5 = (unsigned char *) 0xbffff414 "L����\206\004\b"
这里问题就在于当访问到字符串的结尾时,没有及时退出造成了最后的问题。

修改后的函数如下:
void  Str2Str(void * des, void * src)
{
    unsigned char *pDes = (unsigned char *)des;
    unsigned char *pSrc = (unsigned char *)src;
    unsigned char au8Int[4]  = {0};
    unsigned char u8Idx = 0;
    
    if(dis == NULL || src == NULL)
        return;

    while(*pSrc != '\0')
    {
        while((*pSrc != '.') && (* != '\0'))
        {
            au8Int[u8Idx] = au8Int[u8Idx] * 10 + (*pSrc & 0x0f);
            src++;
        }

        if(*pSrc == '\0')
               break;

        u8Idx++;
        pSrc++;
    }

    sprintf(pDes, "%d.%d.%d.%d", au8Int[0], au8Int[1], au8Int[2], au8Int[3]);
}
避免pSrc,和au8Int的越界访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值