You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:26:00