SrsAutoFree模式,避免内存泄漏和错误
来源:互联网 发布:js中的原型对象 编辑:程序博客网 时间:2024/05/08 09:20
C/C++中内存是一个很难处理的事情,正如强项就是弱项,强大的地方也是致命的地方。
内存不释放就会泄漏,多次释放就会段错误,越界更恐怖。
不释放和多次释放都可以用SrsAutoFree规避,越界就需要工具和经验的问题。
释放和多次释放,原因是内存或者对象的生命周期过程,譬如在一个while循环中,有些时候要释放,有些时候continue就好,就容易出问题。
真的需要活N久的对象吗?很少。大部分的作用域在当前函数和子函数,局部变量就可以搞定,是的,有些时候就是没有办法用局部变量,譬如由一个函数收取的包,在当前函数就需要释放。
考虑下面的逻辑:
int SrsClient::publish(SrsSource* source, bool is_fmle){int ret = ERROR_SUCCESS;SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER);while (true) {// switch to other st-threads.st_usleep(0);SrsCommonMessage* msg = NULL;if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) {srs_error("recv identify client message failed. ret=%d", ret);return ret;}SrsAutoFree(SrsCommonMessage, msg, false);pithy_print.set_age(msg->header.timestamp);// reportableif (pithy_print.can_print()) {srs_trace("<- clock=%u, time=%"PRId64", obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", (int)srs_get_system_time_ms(), pithy_print.get_age(), rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps());}// process audio packetif (msg->header.is_audio() && ((ret = source->on_audio(msg)) != ERROR_SUCCESS)) {srs_error("process audio message failed. ret=%d", ret);return ret;}// process video packetif (msg->header.is_video() && ((ret = source->on_video(msg)) != ERROR_SUCCESS)) {srs_error("process video message failed. ret=%d", ret);return ret;}// process onMetaDataif (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {if ((ret = msg->decode_packet()) != ERROR_SUCCESS) {srs_error("decode onMetaData message failed. ret=%d", ret);return ret;}SrsPacket* pkt = msg->get_packet();if (dynamic_cast<SrsOnMetaDataPacket*>(pkt)) {SrsOnMetaDataPacket* metadata = dynamic_cast<SrsOnMetaDataPacket*>(pkt);if ((ret = source->on_meta_data(msg, metadata)) != ERROR_SUCCESS) {srs_error("process onMetaData message failed. ret=%d", ret);return ret;}srs_trace("process onMetaData message success.");continue;}srs_trace("ignore AMF0/AMF3 data message.");continue;}// process UnPublish event.if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) {if ((ret = msg->decode_packet()) != ERROR_SUCCESS) {srs_error("decode unpublish message failed. ret=%d", ret);return ret;}// flash unpublish.if (!is_fmle) {srs_trace("flash publish finished.");return ret;}SrsPacket* pkt = msg->get_packet();if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) {SrsFMLEStartPacket* unpublish = dynamic_cast<SrsFMLEStartPacket*>(pkt);return rtmp->fmle_unpublish(res->stream_id, unpublish->transaction_id);}srs_trace("ignore AMF0/AMF3 command message.");continue;}}return ret;}从RTMP协议栈拿到包后,使用在这个作用域一定会释放,所以使用AutoFree就可以保证只释放一次,而且一定释放一次。
AutoFree实现很可靠,用C++的构造和析构,以及宏定义就可以搞定。
对比以下代码,没有使用auto free模式:
// ignore when no messages.int count = (int)msgs.size();if (msgs.empty()) { continue;}// all msgs to forward.int i = 0;for (i = 0; i < count; i++) { SrsSharedPtrMessage* msg = msgs[i]; msgs[i] = NULL; // we erased the sendout messages, the msg must not be NULL. srs_assert(msg); ret = client->send_message(msg); if (ret != ERROR_SUCCESS) { srs_error("forwarder send message to server failed. ret=%d", ret); // convert the index to count when error. i++; break; }}// clear sendout mesages.if (i < count) { srs_warn("clear forwarded msg, total=%d, forwarded=%d, ret=%d", count, i, ret);} else { srs_info("clear forwarded msg, total=%d, forwarded=%d, ret=%d", count, i, ret);}msgs.erase(msgs.begin(), msgs.begin() + i);if (ret != ERROR_SUCCESS) { break;}
使用auto free模式后:
// ignore when no messages.if (count <= 0) { srs_verbose("no packets to forward."); continue;}SrsAutoFree(SrsSharedPtrMessage*, msgs, true);// all msgs to forward.for (int i = 0; i < count; i++) { SrsSharedPtrMessage* msg = msgs[i]; srs_assert(msg); msgs[i] = NULL; if ((ret = client->send_message(msg)) != ERROR_SUCCESS) { srs_error("forwarder send message to server failed. ret=%d", ret); return ret; }}
如下图:
- SrsAutoFree模式,避免内存泄漏和错误
- SrsAutoFree模式,避免内存泄漏和错误
- Android 避免内存泄漏
- 避免内存泄漏
- Android 避免内存泄漏
- 如何避免内存泄漏
- 如何避免内存泄漏
- c++避免内存泄漏
- 如何避免内存泄漏
- c++避免内存泄漏
- Android 避免内存泄漏
- 避免android 内存泄漏
- 如何避免内存泄漏?
- 避免内存泄漏问题
- 避免Context内存泄漏
- 详解java内存泄露和如何避免内存泄漏
- 详解java内存泄露和如何避免内存泄漏
- 什么是野指针和内存泄漏?如何避免野指针
- 如何利用多核CPU来加速你的Linux命令 — awk, sed, bzip2, grep, wc等
- 原子级操作 volatile和synchronized
- Linux内核探讨-- 第七章
- 【PAT】1024. Palindromic Number (25)
- c# 3.0 get set 默认值
- SrsAutoFree模式,避免内存泄漏和错误
- MySql学习1
- Compile- vs load-time weaving performance in Spring
- 转:Ubuntu下deb包的安装方法
- java 从零开始,学习笔记之基础入门<数据类型的转换>(五)
- 学习笔记——Linux fork vfork exec clone的关系
- win8系统dll注册失败
- ANT
- 多个数的平均值【简单循环】