首页 > 解决方案 > 尝试实现 bzero 函数会导致分段错误

问题描述

我正在尝试重新编码一个给出分段错误的 bzero 函数,问题是我刚刚使用相同的方法实现了一个像这样的函数(memset)并且效果很好,我看不出两者之间的区别。以下是代码:

#include <stdlib.h>
    
    void    ft_bzero(void   *b, size_t len)
    {
        size_t i;
        unsigned char *mem;
        unsigned char s;
    
        mem = b;
        s = '\0';
        i = 0;
        while (i < len)
        {
            mem[i] = s;
            i++;
        }
    }
    
    #include <stdio.h>
    int main(void)
    {
        char *b = "bzero";
        
        ft_bzero(b, 4);
        return (0);
    }

这是运行良好的 memset 实现:

#include <stdlib.h>
    
    void    *ft_memset(void *dest,  int c, size_t len)
    {
        size_t  i;
        unsigned char   s;
        unsigned char   *mem;
    
        mem = dest;
        s = c;
        i = 0;
        while (i < len)
        {
            mem[i] = s;
            i++;
        }
        return (dest);
    }
    
    #include <stdio.h>
    #include <string.h>
      
    int main()
    {
        char str[50] = "testing the c ft_memset";
        printf("\nBefore memset(): %s\n", str);
      
        ft_memset(str + 13, '.', 8*sizeof(char));
      
        printf("After memset():  %s", str);
        return (0);
    }

尝试了一段时间后发现我的测试是错误的,改变:

int main(void)
        {
            char *b = "bzero";
            
            ft_bzero(b, 4);
            return (0);
        }

int main(void)
{
    char b[5] = "bzero";
    
    ft_bzero(b, 4);
    return (0);
}

解决了这个问题。感谢所有的帮助。

标签: csegmentation-fault

解决方案


  1. 他们为索引使用了错误的类型。它应该不是 size_t unsigned int
  2. 第二个函数应该返回void *值,但它不返回任何 UB。

我会以这种方式实现它(字节版本):

void *ft_memset(void *dest,  int c, size_t len)
{
    unsigned char *mem = dest;

    if(mem)
        while (len--)
            *mem++ = c;
    return dest;
}

或更复杂的版本:

#define UNSIGNEDSIZE 4

static_assert(sizeof(unsigned) == UNSIGNEDSIZE, "This function assumes 32 bit unsigned");

#define TAS(v,s) (((unsigned)((v) & 0xff)) << (s))

void *ft_memset(void *dest,  int c, size_t len)
{
    unsigned char *mem = dest;
    unsigned *umem;
    unsigned uval = TAS(c,24) | TAS (c, 16) | TAS(c, 8) | TAS(c,0);
    unsigned trim = sizeof(unsigned) - ((uintptr_t)mem & (sizeof(unsigned) - 1));

    if(mem)
    {
        len -= trim;
        while (trim--)
            *mem++ = c;
        umem = (void *)mem;
        while(len > 3)
        {
            *umem++ = uval;
            len -= sizeof(unsigned);
        }
        mem = (void *)umem;
        while (len--)
            *mem++ = c;
    }   
    return dest;
}

推荐阅读