2021-08-16

(C/C++)malloc与strcat搭配使用时所需要注意的细节

起因:

在LINUX环境下
做了一个针对ipv6地址的转换接口,其中一个接口功能是”将所设计的ipv6结构转换成用冒分十六进制表达的字符串“;

在我写好代码进行测试时发现代码产生了如下乱码:

(530:0:0:1:0:0:0:0

以下是main里面的调用语句:

int main() {

    ipv6_node node;
    node.ipv6[0] = 0;;
    node.ipv6[1] = 0;;
    node.ipv6[2] = 4294967295;;
    node.ipv6[3] = 2147483648;;

    
    int a= ipv6_add(&node,31);
    printf("ipv6_add是否成功? ans:%d\n",a==0?1:0);
    printf("%u,%u,%u,%u\n",node.ipv6[0],node.ipv6[1],node.ipv6[2],node.ipv6[3]);

    
    unsigned char* ss= malloc(20*sizeof(unsigned char));
    //ss[0]='\0';
	//ss[19]='\0';
    ss=ipv6_stringform(&node,ss);
    printf("调用ipv6_add之后的地址为: %s\n",ss);
    free(ss);
    return 0;
}

ipv6_stringform源代码如下(可忽略):

char* ipv6_stringform(const ipv6_node* ipv6_no, char* string) {
    char* string_temp=string;
    unsigned int temp[8] = { 0,0,0,0,0,0,0,0 };
    int t_index = 0;
    for (int i = 0; i < 4; ++i) {
        for (int j = 0, shift = 16; j < 2; ++j, shift -= 16) {
            temp[t_index++] = (ipv6_no->ipv6[i] >> shift) & 0b1111111111111111;
        }
    }

    for (int j = 0; j < 7; ++j) {
        char s[3] = { 0,0 };
        my_itoa(temp[j], s, 16);
        strcat(string_temp, s);
        strcat(string_temp, ":");
    }
    char s[3] = { 0,0 };
    my_itoa(temp[7], s, 16);
    strcat(string_temp, s);
    return string;
}

产生输出:

ipv6_add是否成功? ans:1 0,1,0,0 当前ipv6地址为:h63�0:0:0:1:0:0:0:0

可以看到虽然输出后半部分输出了正确答案,但是前面会产生乱码。
起初认为是因为内存分配之后没有放入’\0’,倒是函数无法判定当前数组是一个字符串。
所以增加了一句ss[19]='\0';,但随后测试发现还是和之前情况一模一样。

之后观察源码发现,ipv6_stringform函数内部调用的是strcat函数,而拼接规则是将源字符串拼接到目的字符串的结束符’\0’上,直接进行覆盖然后使用源字符串的结束符充当新的字符串结束符;

于是我新增一条语句ss[0]='\0';

新测试结果:

ipv6_add是否成功? ans:1
0,1,0,0
调用ipv6_add之后的地址为: 0:0:0:1:0:0:0:0

现在可以发现ipv6的冒分十六进制表示是没有问题的了。
后面我查看了只进行了malloc内存分配,没有其他初始化操作的字符串数组内部的数据。发现malloc分配之后首先数组数据是众所周知的没有初始化,其次字符串的结束符有可能会在数组随机位置充当无效数据。

于是乎在调用strcat进行拼接时,函数会找到第一个’\0’所在位置,并将其当作目的字符串的结尾。

> 所以在使用malloc进行动态分配,并且要马上使用strcat进行字符串拼接的时候,请在动态数组的第一个值上面填入’\0’。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值