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

C++/Objective-C中避免根对象被删除及强引用问题排查

C++/Objective-C混合代码中的引用生命周期问题

原始代码

#import <YandexMobileAds/YandexMobileAds-Swift.h>

@class AdHook;

namespace MyApp
{
    class AdHolder
    {
    public:

        AdHolder(IosInterstitialAd* cpp_ad);

        AdHook* m_hook;
    };
}

using namespace MyApp;

@interface AdHook : NSObject <YMAInterstitialAdLoaderDelegate, YMAInterstitialAdDelegate>
{
    @public IosInterstitialAd* m_cppAd;

    @public YMAInterstitialAdLoader* m_loader;
    @public YMAInterstitialAd* m_interstitialAd;
}
@end

@implementation AdHook 

- (id)initFromCpp:(IosInterstitialAd *)cpp_ad
{
    if (self = [super init])
    {
        m_cppAd = cpp_ad;
        m_interstitialAd = nil;

        m_loader = [[YMAInterstitialAdLoader alloc]init];
        m_loader.delegate = self;
    }
    return self;
}

AdHolder::AdHolder(IosInterstitialAd* cpp_ad)
{
    [YMAMobileAds enableLogging];

    m_hook = [[AdHook alloc]initFromCpp:cpp_ad];
}

void SomeOtherClass::load()
{
    NSLog(@"IosInterstitialAd::load()");

    YMAAdRequestConfiguration* configuration = [[YMAAdRequestConfiguration alloc]initWithAdUnitID:@"demo-interstitial-yandex"];

    [m_holder->m_hook->m_loader loadAdWithRequestConfiguration:configuration];
}

初始问题

我在C++代码中创建AdHolder类实例,其构造函数会创建Objective-C类AdHook的实例,而AdHook又会创建内部Objective-C对象。但我不清楚m_hook的生命周期,怀疑它会被提前销毁,因为在YMAInterstitialAdLoaderDelegate回调中访问m_hook->m_interstitialAd时出现错误值导致应用崩溃。

请问m_hook是否为强引用?若不是该如何将其设为强引用?


编辑1

我尝试在应用中给多个对象添加retain调用,最终通过给AdHook::m_interstitialAd添加retain调用解决了崩溃问题:

- (void)interstitialAdLoader:(YMAInterstitialAdLoader * _Nonnull)adLoader didLoad:(YMAInterstitialAd * _Nonnull)interstitialAd
{
    NSLog(@"IosInterstitialAd::YMAInterstitialAdLoader::didLoad, %@", interstitialAd);

    m_interstitialAd = [interstitialAd retain];
    m_interstitialAd.delegate = self;
}

应用访问m_interstitialAd时不再崩溃。现在问题变为:AdHook::m_interstitialAd是否为强引用?


回答

关于m_hook的引用类型

AdHolder中的m_hook是普通C指针,不是强引用。Objective-C的ARC仅管控Objective-C对象的引用关系,C指针不在ARC的管理范围内:

  • 你在构造函数中用alloc创建的AdHook实例初始引用计数为1,但因为m_hook是C++指针,ARC不会将其视为强引用持有。一旦没有其他Objective-C强引用指向该实例,ARC会自动释放它,导致后续回调中访问m_hook时出现野指针崩溃。

将m_hook设为强引用的两种方法:

  • ARC环境下:把m_hook声明为__strong AdHook* m_hook;,让ARC自动维护引用计数,保证对象在被持有期间不会被释放。
  • 手动引用计数(MRC)环境下:在AdHolder构造函数中创建实例后调用[m_hook retain],在AdHolder的析构函数中调用[m_hook release],手动控制引用计数。

关于AdHook::m_interstitialAd的引用类型

你添加retain后崩溃解决,说明原本的m_interstitialAd不是强引用:

  • 如果是MRC环境,直接赋值m_interstitialAd = interstitialAd只是指针赋值,不会增加引用计数。当YMAInterstitialAdLoader释放广告对象后,m_interstitialAd就会变成野指针,调用retain手动增加引用计数后,对象会被你持有直到你调用release,因此不再崩溃。
  • 如果是ARC环境,实例变量默认是强引用,但可能存在其他逻辑导致m_interstitialAd被提前释放(比如被弱引用覆盖或其他地方的释放操作)。你可以显式声明为__strong YMAInterstitialAd* m_interstitialAd;来明确强引用,避免混淆。

内容的提问来源于stack exchange,提问作者Dmitriano

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 01:37:31