尝试实现 bzero 函数会出现分段错误
Trying to implement a bzero function gives segmentation fault
我正在尝试重新编码一个会出现分段错误的 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 = '[=10=]';
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);
}
问题已解决。
感谢大家的帮助。
- 他们使用了错误的索引类型。应该是 size_t 而不是
unsigned int
.
- 第二个函数应该 return
void *
值,但它不会 return 任何 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;
}
我正在尝试重新编码一个会出现分段错误的 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 = '[=10=]';
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);
}
问题已解决。 感谢大家的帮助。
- 他们使用了错误的索引类型。应该是 size_t 而不是
unsigned int
. - 第二个函数应该 return
void *
值,但它不会 return 任何 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;
}