[原创]Redis BUG系列(I)——SDS字符串的sdssplitlen函数实现顺序BUG,浪费了计算与内存资源

本文详细介绍了Redis中sdssplitlen函数存在的一个顺序BUG,该BUG会导致每次调用时平均浪费数十次计算资源和5B内存。问题主要在于判断内存分配和字符串切分的顺序。文章提供了修改方法,并通过验证确认了修改能有效解决问题。此BUG影响全版本的Redis,包括从0.0.7到5.0.6。
摘要由CSDN通过智能技术生成

简要

最近在开始看Redis源码,比较各版本的代码看,看着看着就发现一些BUG。写个博客记录一下。
sdssplitlen是一个调用非常频繁的函数,这个BUG将会导致平均每次调用多浪费数十次左右加减法计算资源以及临时浪费5B左右的内存空间。这个BUG影响范围是全版本,从0.07一直到目前最新的5.0.6。

BUG介绍

源码与说明

输入长度为@len的字符串@s,以及长度为@seplen的字符串@sep。
使用@sep对@s进行切分。
切分好的字符串通过返回值@tokens传出,切分得到的个数通过参数@count传出。

/* Split 's' with separator in 'sep'. An array
 * of sds strings is returned. *count will be set
 * by reference to the number of tokens returned.
 *
 * On out of memory, zero length string, zero length
 * separator, NULL is returned.
 *
 * Note that 'sep' is able to split a string using
 * a multi-character separator. For example
 * sdssplit("foo_-_bar","_-_"); will return two
 * elements "foo" and "bar".
 *
 * This version of the function is binary-safe but
 * requires length arguments. sdssplit() is just the
 * same function but for zero-terminated strings.
 */
sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count) {
   
    int elements = 0, slots = 5;
    long start = 0, j;
    sds *tokens;

    if (seplen < 1 || len < 0) return NULL;

    tokens = s_malloc(sizeof(sds)*slots);
    if (tokens == NULL) return NULL;

    if (len == 0) {
   
        *count = 0;
        return tokens;
    }
    for (j = 0; j < (len-(seplen-1)); j++) {
   
        /* make sure there is room for the next element and the final one */
        if (slots < elements+2) {
     // Block 1
            sds *newtokens;

            slots *= 2;
            newtokens = s_realloc(tokens,sizeof(sds)*slots);
            if (newtokens == NULL) goto cleanup;
            tokens = newtokens;
        }
        /* search the separator */
        if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值