像这样使用 malloc 是正确的吗?
Using malloc like this is correct?
我是动态内存分配的新手。
这种类型的使用会造成任何内存泄漏或未分配的内存访问吗?
char *func2(char *str) {
//Do something like writing 10 characters to str
return str;
}
void func1() {
char *str = NULL, *res;
int len = 10;
str = (char *)malloc(len * sizeof(char));
res = func2(str);
free(str);
printf("%s", res);
}
func1
中最后的 printf 语句是否会导致段错误,因为 str
已经被释放,res
会不会是一个没有内存位置指向的悬垂指针?
res
在它引用的内存被释放后使用。这是未定义的行为,可能会或可能不会导致运行时错误。毕竟,未定义的行为是未定义的。
我认为在实践中可能发生的情况是,您的程序将愉快地打印 res
指向的内存中的任何内容。那个记忆并没有消失,你只是说你不会再使用它了。该内存中的内容是未初始化的垃圾,因为您从未向其中写入任何内容。我想你会得到 gobbledygook 的输出。
是的,这是一个错误。我们可以通过将代码变成一个工作示例来演示错误,并且 运行 它在 Valgrind 下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *func2(char *str)
{
strcpy(str, "hello!");
return str;
}
int main()
{
char *str, *res;
int len = 10;
str = malloc(len);
res = func2(str);
free(str);
printf("%s", res);
}
输出向我们展示了发生了什么:
gcc -std=c11 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds 44704791.c -o 44704791
valgrind --leak-check=full ./44704791
==12624== Memcheck, a memory error detector
==12624== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==12624== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==12624== Command: ./44704791
==12624==
==12624== Invalid read of size 1
==12624== at 0x4C2EDA2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12624== by 0x4E80D77: vfprintf (vfprintf.c:1637)
==12624== by 0x4E871F8: printf (printf.c:33)
==12624== by 0x1087B5: main (44704791.c:18)
==12624== Address 0x51d7040 is 0 bytes inside a block of size 10 free'd
==12624== at 0x4C2CDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12624== by 0x10879D: main (44704791.c:17)
==12624== Block was alloc'd at
==12624== at 0x4C2BBAF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12624== by 0x10877D: main (44704791.c:15)
它告诉我们,第 18 行的 printf
试图从第 17 行释放的内存中读取。此外,它还表明有问题的内存是在第 15 行分配的。
这个故事的寓意是,您应该在使用完内存后(而不是之前)释放内存,如果您不清楚您的函数是否拥有传递给它们的内存的所有权,那么这可能很难做到在指针中。
我是动态内存分配的新手。 这种类型的使用会造成任何内存泄漏或未分配的内存访问吗?
char *func2(char *str) {
//Do something like writing 10 characters to str
return str;
}
void func1() {
char *str = NULL, *res;
int len = 10;
str = (char *)malloc(len * sizeof(char));
res = func2(str);
free(str);
printf("%s", res);
}
func1
中最后的 printf 语句是否会导致段错误,因为 str
已经被释放,res
会不会是一个没有内存位置指向的悬垂指针?
res
在它引用的内存被释放后使用。这是未定义的行为,可能会或可能不会导致运行时错误。毕竟,未定义的行为是未定义的。
我认为在实践中可能发生的情况是,您的程序将愉快地打印 res
指向的内存中的任何内容。那个记忆并没有消失,你只是说你不会再使用它了。该内存中的内容是未初始化的垃圾,因为您从未向其中写入任何内容。我想你会得到 gobbledygook 的输出。
是的,这是一个错误。我们可以通过将代码变成一个工作示例来演示错误,并且 运行 它在 Valgrind 下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *func2(char *str)
{
strcpy(str, "hello!");
return str;
}
int main()
{
char *str, *res;
int len = 10;
str = malloc(len);
res = func2(str);
free(str);
printf("%s", res);
}
输出向我们展示了发生了什么:
gcc -std=c11 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds 44704791.c -o 44704791
valgrind --leak-check=full ./44704791
==12624== Memcheck, a memory error detector
==12624== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==12624== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==12624== Command: ./44704791
==12624==
==12624== Invalid read of size 1
==12624== at 0x4C2EDA2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12624== by 0x4E80D77: vfprintf (vfprintf.c:1637)
==12624== by 0x4E871F8: printf (printf.c:33)
==12624== by 0x1087B5: main (44704791.c:18)
==12624== Address 0x51d7040 is 0 bytes inside a block of size 10 free'd
==12624== at 0x4C2CDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12624== by 0x10879D: main (44704791.c:17)
==12624== Block was alloc'd at
==12624== at 0x4C2BBAF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12624== by 0x10877D: main (44704791.c:15)
它告诉我们,第 18 行的 printf
试图从第 17 行释放的内存中读取。此外,它还表明有问题的内存是在第 15 行分配的。
这个故事的寓意是,您应该在使用完内存后(而不是之前)释放内存,如果您不清楚您的函数是否拥有传递给它们的内存的所有权,那么这可能很难做到在指针中。