Как предотвратить удаление корневого объекта в 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];
}

Я создаю экземпляр класса AdHolder в C++ коде, и конструктор AdHolder создает экземпляр класса Objective-C AdHook, который, в свою очередь, создает свои внутренние объекты Objective-C.

Но я не совсем понимаю, каков срок жизни m_hook? И у меня есть подозрение, что он удаляется в какой-то момент, потому что, когда я пытаюсь получить доступ к m_hook->m_interstitialAd из колбэка YMAInterstitialAdLoaderDelegate, я получаю неправильное значение, и приложение завершается с ошибкой.

Является ли m_hook сильной ссылкой? Если нет, то как сделать ее сильной?

Проблема, вероятно, связана с тем, что m_hook не является сильной ссылкой в вашем классе C++. В интеропе Objective-C/C++ обычные указатели не подразумевают владения. Чтобы создать сильную ссылку, измените свой класс AdHolder, чтобы использовать указатель на указатель (AdHook** m_hook;). В конструкторе выделите его с помощью m_hook = new AdHook*; *m_hook = [[AdHook alloc] initFromCpp:cpp_ad];. Добавьте деструктор для очистки: if (m_hook) { [*m_hook release]; delete m_hook; }. При доступе используйте (*holder()->m_hook)->m_loader. Это гарантирует, что объект AdHook не будет неожиданно деаллоцирован. Также убедитесь, что экземпляр AdHolder остается действительным, когда вы получаете доступ к m_hook, так как его преждевременное уничтожение может привести к сбоям.

Ответ или решение

Проблема, с которой вы столкнулись, связана с управлением временем жизни объектов в вашей C++/Objective-C программе. Ваш объект m_hook не сохраняет сильную ссылку на экземпляр класса AdHook, что может привести к его преждевременной деаллокации и вызывает сбой при обращении к его членам.

В Objective-C, для того чтобы гарантировать, что объект будет жить до тех пор, пока он вам нужен, вы должны использовать сильные ссылки (strong или retain).

Для решения вашей проблемы вам нужно внести некоторые изменения в класс AdHolder, чтобы правильно управлять временем жизни объекта m_hook. Возможно, вам стоит изменить определение m_hook так, чтобы он был объектом, а не просто указателем. Вот как это можно сделать:

namespace MyApp
{
    class AdHolder
    {
    public:
        AdHolder(IosInterstitialAd* cpp_ad);
        ~AdHolder();

        AdHook* m_hook;
    };
}

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

    // Создаем объект AdHook и сохраняем его в m_hook
    m_hook = [[AdHook alloc] initFromCpp:cpp_ad];
}

AdHolder::~AdHolder()
{
    // Освобождаем объект AdHook
    [m_hook release];
}

Это обеспечит то, что m_hook будет поддерживать сильную ссылку на экземпляр AdHook, предотвращая его деаллокацию до тех пор, пока экземпляр AdHolder существует.

Также не забудьте, что вам необходимо следить за тем, чтобы экземпляр AdHolder, в свою очередь, был доступен на момент вызова любых методов, которые обращаются к m_hook. Если экземпляр AdHolder будет деаллокирован, то попытка доступа к m_hook вызовет сбой.

Проверка времени жизни

Убедитесь, что вы не создаете экземпляры AdHolder на стеке, если они должны выжить дольше, чем вызов функции, в которой они были созданы. В таких случаях создавайте экземпляры AdHolder в heap-памяти с помощью оператора new, чтобы избежать преждевременной деаллокации:

AdHolder* holder = new AdHolder(cpp_ad);
// используйте holder...
delete holder; // не забудьте освободить память, когда закончите

Резюме

  • Убедитесь, что m_hook является сильной ссылкой, используя подходящую инициализацию и освобождение ресурсов.
  • Контролируйте время жизни экземпляров классов, чтобы избежать доступа к уже деаллоцированным объектам.
  • Используйте new и delete для управления памятью в C++, если не предполагается, что объекты будут существовать в пределах одной функции.

Следуя этим рекомендациям, вы избежите ошибок, связанных с недоступностью объектов в дальнейшем, и сделаете вашу программу более стабильной.

Оцените материал
Добавить комментарий

Капча загружается...