链接:https://www.bilibili.com/video/BV12K411p7GC
本文只是对视频内容归纳整理。
假设从Linux系统的某文件读取5个字符,可写成:
#include <fcntl.h> // ::open()
#include <unistd.h> // ::close()
#include <stdio.h>
int main()
{
int fd = ::open("test.cc", O_RONLY, 0);
if (fd == -1) {
::puts("open failure");
return 1;
}
char str[6] = {};
long nread = ::read(fd, str, sizeof(str-1)); // 读5个字符+'/0'
if (nread < 0) {
::puts("read failure");
::close(fd);
return 1;
}
printf("str = %s\n", str);
// we can do something here
::close(fd);
}
但是这个程序存在潜在的内存泄漏,位置在:
printf("str = %s\n", str);
// we can do something here
如果此时printf抛出异常或do something导致程序提前返回,则无法执行::close(fd)。那么文件描述符就没有被正确关闭。
解决方案是使用智能指针来管理对象的作用域,但fd是整数,而非指针,怎么使用智能指针呢?于是有如下技巧:
#include <fcntl.h> // ::open()
#include <unistd.h> // ::close()
#include <stdio.h>
#include <memory>
int main()
{
int fd = ::open("test.cc", O_RONLY, 0);
if (fd == -1) {
::puts("open failure");
return 1;
}
// 使用unique_ptr管理内存分配对象的作用域
// 这时候我们就可以把程序中其他的::close语句删除了
::std::unique_ptr<int, void (*)(int*)> guard(
&fd, [](int *p) { ::close(*p); });
char str[6] = {};
long nread = ::read(fd, str, sizeof(str-1)); // 读5个字符+'/0'
if (nread < 0) {
::puts("read failure");
return 1;
}
printf("str = %s\n", str);
// we can do something here
}
即保证了内存安全,又不用到处写::close语句,是不是很香?