strlen和strnlen

提示:文章

文章目录

前言

前期疑问:
本文目标:


一、背景

最近

二、

2.1 strncpy规范中的表述

看代码规范提到,输入参数,可能会使用没有结束符的字符串,导致strlen函数越界读书数据,使程序产生未定义的行为。

代码规范的描述是使用strnlen计算字符串长度,再使用strnlen计算字符串长度。将两个长度进行对比,就能判断出输入字符串是否是没有结束符的字符串。

下面编写代码验证一下strlen和strnlen函数的区别。

void StrnlenAndStrlen()
{
    // 这个函数是验证strlen和strnlen区别,并且在检验输入参数中的作用
    char strArray1[] = {'h', 'e', 'l', 'l', 'o'};
    char strArray2[] = {"hello"};
    int len1 = strlen(strArray1);
    int len2 = strlen(strArray2);
    std::cout << "len1:" << len1 << std::endl;
    std::cout << "len2:" << len2 << std::endl;
}

打印结果为

len1:5
len2:5

和预期的不符,strArray1的strlen长度也是5。但是strArray1没有结束符,长度不应该是5的。于是修改代码如下

void StrnlenAndStrlen()
{
    // 这个函数是验证strlen和strnlen区别,并且在检验输入参数中的作用
    char strTest[] = "this is s test string";
    char strArray1[] = {'h', 'e', 'l', 'l', 'o'};
    char strArray2[] = {"hello"};
    int len1 = strlen(strArray1);
    int len2 = strlen(strArray2);
    std::cout << "len1:" << len1 << std::endl;
    std::cout << "len2:" << len2 << std::endl;
    printf("%c\n", *(strArray1 + 5));
    printf("%c\n", *(strArray1 + 6));
    printf("%s\n", strArray1);
}

打印结果如下:

len1:26
len2:5
t
h
1
hellothis is s test string

2.2 额外关于栈的理解

构造出问题情况。因为strArray1在栈顶,所以没有出现预期情况。于是在strArray1上面增加一个字符串局部变量。

由此引出了另外一个问题,即栈的内存分布,经过调试可以看到栈空间内存分布情况如下:

在这里插入图片描述在这里插入图片描述

自绘表格如下

在这里插入图片描述

void StrnlenAndStrlen()
{
    // 这个函数是验证strlen和strnlen区别,并且在检验输入参数中的作用
    char strTest[] = "this is s test string";
    char strArray1[] = {'h', 'e', 'l', 'l', 'o'};
    char strArray2[] = {"hello"};
    int len1 = strlen(strArray1);
    int len2 = strlen(strArray2);
    std::cout << "len1:" << len1 << std::endl;
    std::cout << "len2:" << len2 << std::endl;
    int len3 = strnlen(strArray1,10);
    std::cout << "len3:" << len3 << std::endl;
}

打印结果为len3:10
被strnlen第二个参数无语住了

三、

3.1

再次更新
重新看了下规范,下了下面的验证代码

void StrnlenAndStrlenVerify()
{
    // 这个函数是验证strlen和strnlen区别,并且在检验输入参数中的作用
    char strTest[] = "this is s test string";
    char strArray1[] = {'h', 'e', 'l', 'l', 'o'};
    char strArray2[] = {"hello"};
    int len1 = strlen(strArray1);
    int len2 = strlen(strArray2);
    std::cout << "len1:" << len1 << std::endl;
    std::cout << "len2:" << len2 << std::endl;
    int len3 = strnlen(strArray1, 10);
    std::cout << "len3:" << len3 << std::endl;
    /* 打印结果
     * len1:26
     * len2:5
     * len3:10
     */
    // 下面按照规范中的逻辑来构造strnlen对入参的检查。这个构造是基于传递数组要传数组长度
    // 由此产生一个问题,传递字符串数组也要传递数组长度吗
    ArrayParamCheck(strArray1, 5);
    ArrayParamCheck(strArray2, 6);
    /* 打印结果
     * param error
     * hello
     * 验证了入参为没有结束符的字符串。感觉很鸡肋。只有在防护外部输入的时候才会用到吧
     */
}

上面的代码实现了strnlen对入参的防护和检查

总结

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值