我自己的子串函数 | valgrind 显示一些我不明白的 malloc 错误
My own substring function | valgrind showing some malloc errors I do not understand
任务:
Allocate (with malloc(3)) and return a substring from the string s
. The substring begins at index start
and is of maximum size len
.
Return value: The substring. NULL
if the allocation fails.
你好,几个小时后我决定要求澄清。我有以下功能和一些我无法理解的来自 Valgrind 的错误,即使一切正确也会出现。 (ft_strlen(s)
我从我自己的库中调用,其中还放置了 malloc 的库)。
char *ft_substr(char const *s, unsigned int start, size_t len)
{
unsigned int x;
char *a;
unsigned int i;
i = 0;
if (s == NULL)
return (0);
if (start > ft_strlen(s))
{
if (!(a = (char *)malloc(0*sizeof(char))))
return (0);
return (a);
}
if ((start + len) < ft_strlen(s))
x = len;
else
x = ft_strlen(s) - start;
if (!(a = (char *)malloc((x + 1) * sizeof(char))))
return(0);
while (i < x)
{
a[i] = s[start + i];
i++;
}
a[i] = '[=10=]';
return (a);
}
我故意留下一处错误。如果我假设如果分配失败 return null,为什么下面而不是 0
应该是 1
?无论如何,它不会改变下面显示的错误。
if (!(a = (char *)malloc(0 * sizeof(char))))
错误:
==4817== Invalid read of size 1
==4817== at 0x483FED4: strcmp (in /usr/lib/x86_64-linux-gnu/valgrind vgpreload_memcheck-amd64-linux.so)
==4817== by 0x4039BC: main (ft_substr_test.cpp:28)
==4817== Address 0x4dad0d0 is 0 bytes after a block of size 0 alloc'd
==4817== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4817== by 0x403B58: ft_substr (in /home/tony/42cursus/0lvl_libft_1week/libftTester/a.out)
==4817== by 0x4039A4: main (ft_substr_test.cpp:27)
==4817==
你的函数有多个问题:
start
、x
和 i
的类型应该是 size_t
。
malloc(0)
具有实现定义的行为。您应该为空终止符分配至少 1 个字节,并在 return 将指针指向空字符串之前设置它,或者 return NULL
如果规范要求您应该这样做。
- 函数应该只调用
ft_strlen()
一次。
start > ft_strlen(s)
的特殊情况可以在一般情况下处理,如果一个空字符串应该 returned。
这是修改后的版本:
char *ft_substr(char const *s, size_t start, size_t len) {
size_t i, slen;
char *a;
if (s == NULL) {
return NULL;
}
slen = ft_strlen(s);
if (start > slen) {
start = slen;
}
if (len > slen - start) {
len = slen - start;
}
if (!(a = malloc((len + 1) * sizeof(char)))) {
return NULL;
}
for (i = 0; i < len; i++) {
a[i] = s[start + i];
}
a[i] = '[=10=]';
return a;
}
PS:您可能需要重新格式化代码以适应本地 42 norminette...
在 Linux 系统上,调用 malloc(0)
不一定会 return NULL 指针。它可以 return 一个您不能写入但可以传递给 free
的指针。
因此,当您 return 来自函数的 malloc(0)
的结果时,调用函数会看到一个非空指针并尝试取消引用它。由于这个指针本质上指向一个大小为 0 的缓冲区,因此尝试读取它会读到缓冲区末尾,这就是 valgrind 所抱怨的。
您可以通过 returning NULL 解决此问题:
if (start > ft_strlen(s))
{
return NULL;
}
或者通过为空字符串分配 space 并设置空字节:
if (start > ft_strlen(s))
{
if (!(a = malloc(1)))
return NULL;
*a = 0;
return a;
}
其他一些注意事项:
sizeof(char)
定义为 1,因此您可以将其排除在大小计算之外
- 不要转换
malloc
的 return 值。
- 对空指针使用 NULL 而不是 0
return
语句中的表达式不需要括号。
任务:
Allocate (with malloc(3)) and return a substring from the string
s
. The substring begins at indexstart
and is of maximum sizelen
.Return value: The substring.
NULL
if the allocation fails.
你好,几个小时后我决定要求澄清。我有以下功能和一些我无法理解的来自 Valgrind 的错误,即使一切正确也会出现。 (ft_strlen(s)
我从我自己的库中调用,其中还放置了 malloc 的库)。
char *ft_substr(char const *s, unsigned int start, size_t len)
{
unsigned int x;
char *a;
unsigned int i;
i = 0;
if (s == NULL)
return (0);
if (start > ft_strlen(s))
{
if (!(a = (char *)malloc(0*sizeof(char))))
return (0);
return (a);
}
if ((start + len) < ft_strlen(s))
x = len;
else
x = ft_strlen(s) - start;
if (!(a = (char *)malloc((x + 1) * sizeof(char))))
return(0);
while (i < x)
{
a[i] = s[start + i];
i++;
}
a[i] = '[=10=]';
return (a);
}
我故意留下一处错误。如果我假设如果分配失败 return null,为什么下面而不是 0
应该是 1
?无论如何,它不会改变下面显示的错误。
if (!(a = (char *)malloc(0 * sizeof(char))))
错误:
==4817== Invalid read of size 1
==4817== at 0x483FED4: strcmp (in /usr/lib/x86_64-linux-gnu/valgrind vgpreload_memcheck-amd64-linux.so)
==4817== by 0x4039BC: main (ft_substr_test.cpp:28)
==4817== Address 0x4dad0d0 is 0 bytes after a block of size 0 alloc'd
==4817== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4817== by 0x403B58: ft_substr (in /home/tony/42cursus/0lvl_libft_1week/libftTester/a.out)
==4817== by 0x4039A4: main (ft_substr_test.cpp:27)
==4817==
你的函数有多个问题:
start
、x
和i
的类型应该是size_t
。malloc(0)
具有实现定义的行为。您应该为空终止符分配至少 1 个字节,并在 return 将指针指向空字符串之前设置它,或者 returnNULL
如果规范要求您应该这样做。- 函数应该只调用
ft_strlen()
一次。 start > ft_strlen(s)
的特殊情况可以在一般情况下处理,如果一个空字符串应该 returned。
这是修改后的版本:
char *ft_substr(char const *s, size_t start, size_t len) {
size_t i, slen;
char *a;
if (s == NULL) {
return NULL;
}
slen = ft_strlen(s);
if (start > slen) {
start = slen;
}
if (len > slen - start) {
len = slen - start;
}
if (!(a = malloc((len + 1) * sizeof(char)))) {
return NULL;
}
for (i = 0; i < len; i++) {
a[i] = s[start + i];
}
a[i] = '[=10=]';
return a;
}
PS:您可能需要重新格式化代码以适应本地 42 norminette...
在 Linux 系统上,调用 malloc(0)
不一定会 return NULL 指针。它可以 return 一个您不能写入但可以传递给 free
的指针。
因此,当您 return 来自函数的 malloc(0)
的结果时,调用函数会看到一个非空指针并尝试取消引用它。由于这个指针本质上指向一个大小为 0 的缓冲区,因此尝试读取它会读到缓冲区末尾,这就是 valgrind 所抱怨的。
您可以通过 returning NULL 解决此问题:
if (start > ft_strlen(s))
{
return NULL;
}
或者通过为空字符串分配 space 并设置空字节:
if (start > ft_strlen(s))
{
if (!(a = malloc(1)))
return NULL;
*a = 0;
return a;
}
其他一些注意事项:
sizeof(char)
定义为 1,因此您可以将其排除在大小计算之外- 不要转换
malloc
的 return 值。 - 对空指针使用 NULL 而不是 0
return
语句中的表达式不需要括号。