malloc 和 free 如何处理错误?
How does malloc and free work with errors?
我刚刚学习 C 语言中的 malloc() 和 free(),偶然发现了一个我在任何地方都找不到的重要问题。让我们以这个简单的代码片段为例:
int main(int argc, char *argv[])
{
char *test = malloc(sizeof(char) * 30);
strcpy(test, "test");
FILE *file = fopen("filename", "r");
if (file == NULL){
error("Couldn't open file");
}
free(test);
...
}
malloc()
和 free()
现在如何处理这个调用 exit(EXIT_FAILURE)
的错误。因为代码没有达到free(test)
如果出现错误,String test没有释放,是不是有问题?还是程序退出时自动释放?
这个问题的答案是自动释放。
原因是对于 Linux 上的 C,总是以两种不同的方式跟踪内存。
- 每个程序都会跟踪它分配的内存以及每次分配的内存大小。这是 malloc 级别的跟踪。
- 操作系统会跟踪哪些内存属于哪个程序。这是页面级跟踪。
换句话说,如果一个程序未能释放一块内存,那么操作系统仍然知道那块内存是属于那个程序的。程序退出时可以释放内存
那么,如果操作系统可以为程序分配内存并释放它,为什么还存在 malloc 级跟踪?当 Linux 为程序分配内存时,它只能以称为“页面”的 4KB 块来分配。如果你想分配 10 个字节来保存一个字符串,那么分配一个完整的页面,并且只使用前 10 个字节是非常浪费的。为此,malloc() 向操作系统1 以4KB 页为单位申请内存,如果你要求更小的一块,则将它们切成更小的块。然后,它跟踪每个分配。
如果你忘记释放一块内存,而你的程序退出了,没关系,因为操作系统无论如何都会释放内存。释放错误路径中的内存仍然是明智的,因为有一天您可能想要更改程序以便它从错误中恢复而不是立即退出。
1 我在这里掩盖了一些细节。
我刚刚学习 C 语言中的 malloc() 和 free(),偶然发现了一个我在任何地方都找不到的重要问题。让我们以这个简单的代码片段为例:
int main(int argc, char *argv[])
{
char *test = malloc(sizeof(char) * 30);
strcpy(test, "test");
FILE *file = fopen("filename", "r");
if (file == NULL){
error("Couldn't open file");
}
free(test);
...
}
malloc()
和 free()
现在如何处理这个调用 exit(EXIT_FAILURE)
的错误。因为代码没有达到free(test)
如果出现错误,String test没有释放,是不是有问题?还是程序退出时自动释放?
这个问题的答案是自动释放。
原因是对于 Linux 上的 C,总是以两种不同的方式跟踪内存。
- 每个程序都会跟踪它分配的内存以及每次分配的内存大小。这是 malloc 级别的跟踪。
- 操作系统会跟踪哪些内存属于哪个程序。这是页面级跟踪。
换句话说,如果一个程序未能释放一块内存,那么操作系统仍然知道那块内存是属于那个程序的。程序退出时可以释放内存
那么,如果操作系统可以为程序分配内存并释放它,为什么还存在 malloc 级跟踪?当 Linux 为程序分配内存时,它只能以称为“页面”的 4KB 块来分配。如果你想分配 10 个字节来保存一个字符串,那么分配一个完整的页面,并且只使用前 10 个字节是非常浪费的。为此,malloc() 向操作系统1 以4KB 页为单位申请内存,如果你要求更小的一块,则将它们切成更小的块。然后,它跟踪每个分配。
如果你忘记释放一块内存,而你的程序退出了,没关系,因为操作系统无论如何都会释放内存。释放错误路径中的内存仍然是明智的,因为有一天您可能想要更改程序以便它从错误中恢复而不是立即退出。
1 我在这里掩盖了一些细节。