面试题答案
一键面试处理大量并发连接带来内存管理问题的方法
- 对象池技术:预先创建一定数量的对象(如连接对象),当有新连接时从对象池中获取,连接关闭时放回对象池。避免频繁的动态内存分配与释放。
- 智能指针:在C++中使用智能指针(如
std::unique_ptr
、std::shared_ptr
)来管理动态分配的内存。智能指针会在对象不再被使用时自动释放其占用的内存,有效防止内存泄漏。
可能遇到的内存泄漏场景及解决方案
- 场景:在处理连接时,手动分配了内存用于存储连接相关的数据(如缓冲区),但在连接关闭时忘记释放这些内存。
解决方案:使用智能指针管理内存。// 错误示例 void handle_connection(int fd) { char* buffer = new char[1024]; // 使用buffer处理连接 // 没有释放buffer }
// 正确示例 void handle_connection(int fd) { std::unique_ptr<char[]> buffer(new char[1024]); // 使用buffer处理连接 // 函数结束时,buffer会自动释放 }
- 场景:在事件回调函数中动态分配内存,但回调函数结束后没有释放。例如,在libevent的
event_callback_fn
中分配了内存。
解决方案:可以将智能指针作为参数传递给回调函数,或者在回调函数内部使用智能指针管理内存。static void read_callback(int fd, short event, void* arg) { MyData* data = new MyData(); // 使用data处理数据 // 没有释放data }
static void read_callback(int fd, short event, void* arg) { std::unique_ptr<MyData> data(new MyData()); // 使用data处理数据 // 函数结束时,data会自动释放 }
- 场景:在一个复杂的连接处理逻辑中,存在多层嵌套的动态内存分配,其中某些内层分配的内存依赖外层分配的内存,但在释放内存时顺序错误,导致部分内存无法释放。
解决方案:在类的析构函数中正确处理内存释放顺序。void complex_connection_handler(int fd) { Connection* conn = new Connection(); conn->sub_data = new SubData(); // 处理连接 delete conn; // 这里先释放conn,导致sub_data内存泄漏 }
class Connection { public: ~Connection() { delete sub_data; } SubData* sub_data; }; void complex_connection_handler(int fd) { Connection* conn = new Connection(); // 处理连接 delete conn; }
或者使用智能指针,让其自动管理内存释放顺序。 ```cpp class Connection { public: std::unique_ptr sub_data; };
void complex_connection_handler(int fd) {
std::unique_ptr<Connection> conn(new Connection());
conn->sub_data.reset(new SubData());
// 处理连接
// conn自动释放时,sub_data也会自动释放
}
```