简体   繁体   English

在非ARC项目中释放对象,对象在ARC库中声明

[英]Release an object in a non-ARC project, object is declared in an ARC library

Well I am working on a non-ARC project, but use Philipp Kyeck's socketio library which is written using ARC. 那么我正在研究一个非ARC项目,但是使用了使用ARC编写的Philipp Kyeck的socketio库 I am using the method explained in this tutorial merge non-ARC project and ARC library. 我正在使用教程中介绍的方法合并非ARC项目和ARC库。

In my ViewController file I am initializing the socket using 在我的ViewController文件中,我正在使用初始化套接字

 SockIO *chatSockIO = [[SocketIO alloc] initWithDelegate:self];

and when I need to disconnect, I call 当我需要断开时,我打电话

[chatSockIO disconnect];

which results socketIODidDisconnect delegate method to fire. 这会导致socketIODidDisconnect委托方法触发。

- (void) socketIODidDisconnect:(SocketIO *)socket{
   [chatSockIO release]; ==> is this call needed?
}

Now my question is about the line [chatSockIO release] . 现在我的问题是关于行[chatSockIO release] Should we need to release an object which itself is defined in ARC mode, but is used in a non-ARC project? 我们是否需要释放一个本身在ARC模式下定义但在非ARC项目中使用的对象?

Now when I tried the release, I got an exception saying 现在,当我尝试发布时,我得到了一个例外

-[SocketIO retain]: message sent to deallocated instance 0x6fec370

but when I commented out that line, I am getting a memory leak and dealloc in my library object not getting called at all 但当我注释掉那一行时,我的内存泄漏和dealloc在我的库对象中根本没有被调用

Bounty Time!! 赏金时间!!

Forget the library I mentioned, crash in my code and leaks.. What is the usual practice when using an object defined using ARC method, in a non-ARC project. 忘记我提到的库,崩溃我的代码和泄漏.. 在非ARC项目中使用使用ARC方法定义的对象时的常规做法是什么。 Should I only alloc it, or should I alloc and release it after use? 我应该只分配它,还是应该在使用后分配和释放它?

EDIT:Some more info. 编辑:更多信息。

I run zombie instrument on the crash, and this is what it had to say.. It shows the call to alloc and release functions. 我在崩溃时运行zombie instrument,这就是它所说的..它显示了对alloc和release函数的调用。

#   Address     Category    Event Type  RefCt   Timestamp       Size    Responsible Library     Responsible Caller
0   0x72d5da0   SocketIO    Malloc      1       00:09.700.274   64      MyProject           -[MyViewController sendRequestForSocketIOPush]
1   0x72d5da0   SocketIO    Retain      2       00:09.700.317   0       MyProject           -[SocketIO initWithDelegate:]
2   0x72d5da0   SocketIO    Release     1       00:09.700.320   0       MyProject           -[SocketIO initWithDelegate:]
3   0x72d5da0   SocketIO    Retain      2       00:09.700.440   0       Foundation          -[NSURLConnectionInternal initWithInfo:]
4   0x72d5da0   SocketIO    Retain      3       00:10.413.717   0       Foundation          -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]
5   0x72d5da0   SocketIO    Release     2       00:10.413.761   0       Foundation          -[NSURLConnectionInternalConnection invokeForDelegate:]
6   0x72d5da0   SocketIO    Retain      3       00:10.413.797   0       Foundation          -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]
7   0x72d5da0   SocketIO    Release     2       00:10.413.811   0       Foundation          -[NSURLConnectionInternalConnection invokeForDelegate:]
8   0x72d5da0   SocketIO    Retain      3       00:10.413.816   0       Foundation          -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]
9   0x72d5da0   SocketIO    Release     2       00:10.415.087   0       Foundation          -[NSURLConnectionInternalConnection invokeForDelegate:]
10  0x72d5da0   SocketIO    Retain      3       00:10.415.214   0       Foundation          -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]
11  0x72d5da0   SocketIO    Release     2       00:10.415.216   0       Foundation          -[NSURLConnectionInternalConnection invokeForDelegate:]
12  0x72d5da0   SocketIO    Release     1       00:10.415.275   0       Foundation          -[NSURLConnectionInternalConnection invokeForDelegate:]
13  0x72d5da0   SocketIO    Retain      2       00:10.969.432   0       GraphicsServices    GSEventRunModal
14  0x72d5da0   SocketIO    Release     1       00:10.969.433   0       GraphicsServices    GSEventRunModal
15  0x72d5da0   SocketIO    Retain      2       00:10.969.434   0       GraphicsServices    GSEventRunModal
16  0x72d5da0   SocketIO    Release     1       00:10.969.456   0       GraphicsServices    GSEventRunModal
17  0x72d5da0   SocketIO    Retain      2       00:10.969.459   0       GraphicsServices    GSEventRunModal
18  0x72d5da0   SocketIO    Retain      3       00:10.969.488   0       Foundation          -[NSCFTimer initWithFireDate:interval:target:selector:userInfo:repeats:]
19  0x72d5da0   SocketIO    Release     2       00:10.976.115   0       MyProject           -[SocketIO setTimeout]
20  0x72d5da0   SocketIO    Retain      3       00:10.976.125   0       Foundation          -[NSCFTimer initWithFireDate:interval:target:selector:userInfo:repeats:]
21  0x72d5da0   SocketIO    Release     2       00:10.976.161   0       GraphicsServices    GSEventRunModal
22  0x72d5da0   SocketIO    Retain      3       00:13.935.328   0       GraphicsServices    GSEventRunModal
23  0x72d5da0   SocketIO    Release     2       00:13.935.373   0       MyProject           -[SocketIO setTimeout]
24  0x72d5da0   SocketIO    Retain      3       00:13.935.399   0       Foundation          -[NSCFTimer initWithFireDate:interval:target:selector:userInfo:repeats:]
25  0x72d5da0   SocketIO    Release     2       00:13.935.685   0       MyProject           -[SocketIO onDisconnect]
26  0x72d5da0   SocketIO    Release     1       00:13.935.705   0       MyProject           -[MyViewController socketIODidDisconnect:]
27  0x72d5da0   SocketIO    Release     0       00:13.935.716   0       GraphicsServices    GSEventRunModal
28  0x72d5da0   SocketIO    Zombie      -1      00:13.936.298   0       GraphicsServices    GSEventRunModal

To answer your question: 回答你的问题:

If you use an ARC-managed object from non-ARC code, you use it just as you would use a non-ARC object: If you create or retain it, you have to release or autorelease it. 如果您使用非ARC代码中的ARC管理对象,则可以像使用非ARC对象一样使用它:如果您创建或保留它,则必须释放或自动释放它。

Regarding your issue: 关于你的问题:

In on of your comments you mentioned that you tried to fix the problem with initializing like this 在您的评论中,您提到过您试图通过这样的初始化来解决问题

self.chatSockIO = [[[SocketIO alloc] initWithDelegate:self] autorelease];

and in socketIODidDisconnect 并在socketIODidDisconnect

self.chatSockIO = nil;

That should work fine, provided that the chatSockIO property has retain semantics, and that only one SocketIO object is used at a time. 如果chatSockIO属性具有retain语义,并且一次只使用一个SocketIO对象,那应该可以正常工作。

The Zombie output gives a hint on what's going wrong: Zombie输出提示出现了什么问题:

  • In the second to last line, you release the object, the retain count drops to 0, and the object is deallocated. 在倒数第二行中,释放对象,保留计数降为0,并释放对象。 That is what you would expect. 这就是你所期望的。
  • In the last line however, it is tried to retain the object from the run loop. 但是,在最后一行中,尝试从运行循环中保留对象。 You know it's a retain because of the exception you get without NSZombie . 你知道这是一个保留,因为没有NSZombie你会得到例外。
  • That means although you are done with the object, it still receives calls from somewhere. 这意味着虽然你完成了对象,它仍然会从某个地方接收调用。 This is unexpected. 这是出乎意料的。

It could be either something in your code, or an error in one of the libraries you are using. 它可能是您代码中的某些内容,也可能是您正在使用的某个库中的错误。 Just a hunch: In SocketIO.m replace these lines in -onDisconnect 只是预感:在SocketIO.m替换-onDisconnect这些行

if (_webSocket != nil) {
    [_webSocket close];
}

with

if (_webSocket != nil) {
    [_webSocket close];
    _webSocket.delegate = nil;
}

This may not solve your problem, but in any case its usually a TERRIBLE idea to release an object in a delegate call - it may get dealloc'd while still doing work, and particularly if the object is under ARC, may not have a dealloc method. 这可能无法解决您的问题,但无论如何,它通常是一个在委托调用中释放对象的可怕想法 - 它可能在仍然工作时被释放,特别是如果对象在ARC下,可能没有dealloc方法。

So convert your close delegate call to this: 因此,将您的close委托调用转换为:

- (void) socketIODidDisconnect:(SocketIO *)socket
{
   chatSockIO.delegate = nil; // don't want any more messages
   dispatch_async(dispatch_get_main_gueue(), ^{ self.chatSockIO = nil; }); // typed in text editor
   // your question - is the release needed? Well, under virtually every scenario yes, but I don't know this framework
}

Whether this fixes your problem or not, you should be doing the release in this manner - on the main thread AFTER the delegate has returned. 无论这是否解决了您的问题,您应该以这种方式进行发布 - 在代理返回后的主线程上。 If you look at your code, you should do EXACTLY with this ARC class as you would with a normal class. 如果您查看代码,您应该像使用普通类一样完全使用此ARC类。 The interoperability is excellent, I used several NON-ARC projects in my ARC app, and others have successfully done the reverse. 互操作性非常好,我在ARC应用程序中使用了几个NON-ARC项目,其他人已成功完成相反的操作。

In my experience I wouldn't mix ARC and non-ARC expect small small chunks of code. 根据我的经验,我不会混合ARC和非ARC期望小块的代码。 I wasted way to much time to try to find leaks and crash bugs. 我浪费了很多时间来试图找到泄漏和崩溃的错误。

If you can't convert your program to ARC, consider using the non-ARC version of sockIO: https://github.com/pkyeck/socket.IO-objc/tree/non-arc 如果您无法将程序转换为ARC,请考虑使用非ARC版本的sockIO: https//github.com/pkyeck/socket.IO-objc/tree/non-arc

That will probably save you a lot of headaches. 这可能会为你节省很多麻烦。

I had felt similar issues. 我有类似的问题。 I solved this by setting @property(nonatomic, retain) over the class. 我通过在类上设置@property(nonatomic, retain)来解决这个问题。 In your case it should be, 在你的情况下它应该是,

in .h 在.h

  @property(nonatomic, retain) SockIO *socketIO;

in .m 在.m

   @synthesize socketIO;
   chatSockIO = [[SocketIO alloc] initWithDelegate:self];

And you wont get crash your App again ! 而且你不会再次崩溃你的应用程序!

ARC and non ARC objects mix fine. ARC和非ARC对象混合得很好。 Classes that are implemented using ARC can safely be used from non-ARC code. 使用ARC实现的类可以安全地从非ARC代码中使用。 Whenever there's an ownership error the problem is probably in your code. 每当出现所有权错误时,问题可能在您的代码中。

Without seeing code it's not possible to find the error but it's probably some simple over-release. 没有看到代码就不可能找到错误,但它可能是一些简单的过度释放。

Look at all the places in MyProject where the Instruments trace shows a Release event, like -[SocketIO setTimeout] , -[SocketIO onDisconnect] and -[MyViewController socketIODidDisconnect:] . 查看MyProject中仪器跟踪显示Release事件的所有位置,如-[SocketIO setTimeout]-[SocketIO onDisconnect]-[MyViewController socketIODidDisconnect:] Check if there are improper ownership transfers, like assigning an instance variable handled by a retain property or similar. 检查是否存在不正确的所有权转移,例如分配由保留属性或类似处理的实例变量。

I am currently working on a project that I did something similar and the way I solved it was to switch the non-ARC project to ARC. 我目前正在开发一个项目,我做了类似的事情,我解决它的方法是将非ARC项目切换到ARC。 Xcode transfers everything over for you and for me solved all my memory leaks and other issues. Xcode为您转移所有内容,并为我解决了所有内存泄漏和其他问题。

To change over to ARC you need to: 要切换到ARC,您需要:

1. Click Edit->Refactor->Convert to Objective-C ARC 1.单击编辑 - >重构 - >转换为Objective-C ARC

2. Click your projects target and in the drop down, select the files you want to convert to ARC 2.单击项目目标,然后在下拉列表中选择要转换为ARC的文件

3. Click Check once you have selected the right files 3.选择正确的文件后,单击“检查”

4. Click next and wait until conversion is done. 4.单击“下一步”,等待转换完成。

5. Click the "Update" button to update your code. 5.单击“更新”按钮以更新代码。

6. Review your code 6.检查您的代码

Hope that helps. 希望有所帮助。 It helped me 它帮助了我

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM