生活随笔
收集整理的這篇文章主要介紹了
SrsAutoFree模式,避免内存泄漏和错误
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
C/C++中內(nèi)存是一個很難處理的事情,正如強(qiáng)項(xiàng)就是弱項(xiàng),強(qiáng)大的地方也是致命的地方。
內(nèi)存不釋放就會泄漏,多次釋放就會段錯誤,越界更恐怖。
不釋放和多次釋放都可以用SrsAutoFree規(guī)避,越界就需要工具和經(jīng)驗(yàn)的問題。
釋放和多次釋放,原因是內(nèi)存或者對象的生命周期過程,譬如在一個while循環(huán)中,有些時候要釋放,有些時候continue就好,就容易出問題。
真的需要活N久的對象嗎?很少。大部分的作用域在當(dāng)前函數(shù)和子函數(shù),局部變量就可以搞定,是的,有些時候就是沒有辦法用局部變量,譬如由一個函數(shù)收取的包,在當(dāng)前函數(shù)就需要釋放。
考慮下面的邏輯:
[cpp] ?view plaincopy
int ?SrsClient::publish(SrsSource*?source,? bool ?is_fmle)?? {?? ????int ?ret?=?ERROR_SUCCESS;?? ?????? ????SrsPithyPrint?pithy_print(SRS_STAGE_PUBLISH_USER);?? ?????? ????while ?( true )?{?? ?????????? ????????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);?? ?? ?????????? ????????if ?(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());?? ????????}?? ?????????? ?????????? ????????if ?(msg->header.is_audio()?&&?((ret?=?source->on_audio(msg))?!=?ERROR_SUCCESS))?{?? ????????????srs_error("process?audio?message?failed.?ret=%d" ,?ret);?? ????????????return ?ret;?? ????????}?? ?????????? ????????if ?(msg->header.is_video()?&&?((ret?=?source->on_video(msg))?!=?ERROR_SUCCESS))?{?? ????????????srs_error("process?video?message?failed.?ret=%d" ,?ret);?? ????????????return ?ret;?? ????????}?? ?????????? ?????????? ????????if ?(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 ;?? ????????}?? ?????????? ?????????? ????????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;?? ????????????}?? ?????????????? ?????????????? ????????????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協(xié)議棧拿到包后,使用在這個作用域一定會釋放,所以使用AutoFree就可以保證只釋放一次,而且一定釋放一次。
AutoFree實(shí)現(xiàn)很可靠,用C++的構(gòu)造和析構(gòu),以及宏定義就可以搞定。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 /* The MIT License (MIT) Copyright (c) 2013 winlin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef SRS_CORE_AUTO_FREE_HPP #define SRS_CORE_AUTO_FREE_HPP /* #include <srs_core_auto_free.hpp> */ #include <srs_core.hpp> /** * auto free the instance in the current scope. */ #define SrsAutoFree(className, instance, is_array) \ __SrsAutoFree<className> _auto_free_##instance(&instance, is_array) template < class T > class __SrsAutoFree { private: T ** ptr ; bool is_array ; public: /** * auto delete the ptr. * @is_array a bool value indicates whether the ptr is a array. */ __SrsAutoFree ( T ** _ptr , bool _is_array ){ ptr = _ptr ; is_array = _is_array ; } virtual ~ __SrsAutoFree (){ if ( ptr == NULL || * ptr == NULL ) { return ; } if ( is_array ) { delete [] * ptr ; } else { delete * ptr ; } * ptr = NULL ; } }; #endif
?來自CODE的代碼片 srs_core_auto_free.hpp
對比以下代碼,沒有使用auto free模式:
[cpp] ?view plaincopy
?? int ?count?=?( int )msgs.size();?? if ?(msgs.empty())?{?? ????????continue ;?? }?? ?? ?? int ?i?=?0;?? for ?(i?=?0;?i?<?count;?i++)?{?? ????????SrsSharedPtrMessage*?msg?=?msgs[i];?? ????????msgs[i]?=?NULL;?? ?? ?????????? ????????srs_assert(msg);?? ?????????? ????????ret?=?client->send_message(msg);?? ????????if ?(ret?!=?ERROR_SUCCESS)?{?? ????????????????srs_error("forwarder?send?message?to?server?failed.?ret=%d" ,?ret);?? ?? ?????????????????? ????????????????i++;?? ?????????????????? ????????????????break ;?? ????????}?? }?? ?? ?? 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模式后:
[cpp] ?view plaincopy
?? if ?(count?<=?0)?{?? ????srs_verbose("no?packets?to?forward." );?? ????continue ;?? }?? SrsAutoFree(SrsSharedPtrMessage*,?msgs,?true );?? ?? ?? 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;?? ????}?? }??
如下圖:
總結(jié)
以上是生活随笔 為你收集整理的SrsAutoFree模式,避免内存泄漏和错误 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。