iOS端AppRTC自定义音频通话接口开发遇RtcEventLog崩溃求助
问题排查与修复建议
从你贴的代码和崩溃现象来看,RtcEventLog的生命周期管理错误是触发崩溃的核心原因,下面我会一步步拆解问题,同时也给你梳理下代码里的其他潜在风险:
1. 崩溃的直接原因:悬空的RtcEventLog指针
先看你代码里关于RtcEventLog的这段:
std::unique_ptr<RtcEventLog> event_log = webrtc::RtcEventLog::Create(); webrtc::Call::Config callConfig = webrtc::Call::Config(event_log.get()); // ... 中间一堆配置操作 std::unique_ptr<RtcEventLog> event_logg = webrtc::RtcEventLog::Create(); callConfig.event_log = event_logg.get(); g_call = webrtc::Call::Create(callConfig);
这里有两个致命问题:
- 你先后创建了两个
RtcEventLog实例,最后传给Call的是event_logg的裸指针,但event_logg是局部的std::unique_ptr——当这个初始化函数执行完毕返回时,event_logg会自动销毁它持有的RtcEventLog对象,此时g_call内部保存的event_log指针就变成了悬空指针,后续任何触发RtcEventLog日志写入的操作都会直接导致崩溃。 - 第一个
event_log实例完全是多余的,不仅浪费资源,还增加了代码的混乱度。
修复方法:
把RtcEventLog的生命周期和g_call绑定,比如将它声明为全局智能指针(和g_call同生命周期):
// 全局变量区声明,和g_call等变量放一起 std::unique_ptr<webrtc::RtcEventLog> g_event_log; // 初始化Call的代码里: g_event_log = webrtc::RtcEventLog::Create(); webrtc::Call::Config callConfig = webrtc::Call::Config(g_event_log.get()); // 配置码率等参数 callConfig.bitrate_config.max_bitrate_bps = 500*1000; callConfig.bitrate_config.min_bitrate_bps = 100*1000; callConfig.bitrate_config.start_bitrate_bps = 250*1000; // ... 其他AudioState等配置,不要再创建第二个event_logg // 直接用g_event_log的指针即可,不需要重新赋值callConfig.event_log g_call = webrtc::Call::Create(callConfig);
这样只要g_call还存在,g_event_log就不会被释放,彻底避免悬空指针问题。
2. 代码里的其他潜在风险(可能引发后续崩溃或内存泄漏)
除了RtcEventLog的问题,你的代码还有几个需要调整的地方:
- VoEWrapper的内存泄漏:你用
new cricket::VoEWrapper()创建了g_voe,但没有对应的delete操作,长期运行会导致内存泄漏。建议换成智能指针管理:std::unique_ptr<cricket::VoEWrapper> g_voe = std::make_unique<cricket::VoEWrapper>(); - AudioProcessing的生命周期:
webrtc::AudioProcessing::Create()返回的是scoped_refptr,你直接赋值给audio_state_config.audio_processing,需要确保它的生命周期长于AudioState和Call。可以把它声明为全局的scoped_refptr:rtc::scoped_refptr<webrtc::AudioProcessing> g_audio_processing;,然后初始化时g_audio_processing = webrtc::AudioProcessing::Create(); - AudioLoopbackTransport的内存泄漏:
new AudioLoopbackTransport()创建的g_audioSendTransport没有释放,同样建议用智能指针:std::unique_ptr<AudioLoopbackTransport> g_audioSendTransport = std::make_unique<AudioLoopbackTransport>(); - 音频通道的清理:你创建了发送和接收两个VOE通道,在结束通话时一定要调用
g_voe->base()->DeleteChannel(g_audioSendChannelId)和g_voe->base()->DeleteChannel(g_audioReceiveChannelId),否则会导致音频资源泄漏。
3. Call模块调用流程的合理性优化
你的初始化流程大体方向是对的,但有几个可以简化的点:
- 不需要创建两个RtcEventLog实例,一个就足够给Call使用
- 如果没有自定义混音需求,不需要手动创建
AudioMixerImpl,WebRTC会自动创建默认的混音器 - 注意:你当前用的
AudioLoopbackTransport是回环测试用的,实际局域网通话需要替换成自定义的Transport,实现SendPacket和SignalPacketLoss等方法,把音频数据包发送到对方的IP和端口,同时接收对方发来的数据包。
如果按照上面的方案调整后仍然崩溃,建议提供崩溃时的堆栈信息,这样可以更精准地定位是RtcEventLog的哪个具体操作触发了崩溃。
内容的提问来源于stack exchange,提问作者docMan
相关产品推荐
相关产品推荐

