Note that there are some explanatory texts on larger screens.

plurals
  1. PONSImage setImage: method causes memory leaks in ARC?
    primarykey
    data
    text
    <p>I am new in Apple developing (about 3 months) and now using Xcode 4.5.1 with ARC of all my projects. I was trying display an mjpeg video in my app (also, <b>ARC</b>). As mjpeg coding is based on independent jpeg images, I used <b>NSImageWell</b> to display every frame of mjpeg flow. However, when I switched frame, I noticed the <b>memory leak</b>.</p> <p>The .h file:</p> <pre><code>#import &lt;Cocoa/Cocoa.h&gt; @interface AMCImagiaTestViewController : NSViewController - (void) startVideo; - (void) stopVideo; @end </code></pre> <p>The .m file:</p> <pre><code>#import "AMCImagiaTestViewController.h" #include "AMCCommonLib.h" // My UNIX-like system call library. Used in the thread to call socket functions. Don't mind. #import "TTImage.h" // This is NSImage. I only add an NSLog() in -dealloc method /* forward declaration for a POSIX thread which receives jpeg data. This thread receives jpeg images sent by a process of a Linux PC. The socket content is simple enough: standard jpeg data started with FFD8 and end with FFD9 */ void *threadReceiveFrameData(void *arg); @interface AMCImagiaTestViewController () @property (nonatomic, assign) IBOutlet NSImageView *imageVideoFrame; // the outlet to the image in nib file @property (nonatomic, assign) pthread_t hdlThread; /* here are some properties used in thread but I can close or release if I kill it outside its thread loop */ @property (nonatomic, assign) int sockFd; @property (nonatomic, assign) BOOL isThreadRunning; @property (nonatomic, retain) NSData *dataForImage; @property (nonatomic, retain) TTImage *tempImage; @end @implementation AMCImagiaTestViewController ... // some non-important methods - (void) startVideo { [self stopVideo]; /* Start the receiving thread */ pthread_create(&amp;_hdlThread, NULL, threadReceiveFrameData, (__bridge void*)self); } - (void) stopVideo { if (_isThreadRunning) { pthread_cancel(_hdlThread); usleep(100000); pthread_join(_hdlThread, NULL); _hdlThread = 0; if (_sockFd) { simpleSocketClose(_sockFd); _sockFd = 0; } } } ... @end // end of @implementation AMCImagiaTestViewController // Now comes to the POSIX thread void *threadReceiveFrameData(void *arg) { @autoreleasepool { AMCImagiaTestViewController *ctrl; struct sockaddr_in sockMessage; uint8_t buff[60001]; ssize_t dataLen; memset(buff, 0, sizeof(buff)); ctrl = (__bridge AMCImagiaTestViewController*) arg; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); ctrl.isThreadRunning = YES; /* socket(). create a UDP socket */ ctrl.sockFd = simpleSocketCreate_udp(); if (!ctrl.sockFd) { SYS_PERROR(); // a package of perror(). don't mind goto THREAD_EXIT; } /* bind(). 22222 is the local port */ if (simpleSocketBind_udp(ctrl.sockFd, 22222) &lt; 0) { SYS_PERROR(); goto THREAD_EXIT; } NSLog(@"pthread init OK"); do { /* my package of recvfrom(). The first NULL means receive from any IP. The second NULL means never timeout (using the select() system call) */ dataLen = simpleSocketReceiveFrom_udp(ctrl.sockFd, NULL, &amp;sockMessage, buff, sizeof(buff) - 1, NULL); if (dataLen &gt; 0) { //NSLog(@"received: %ld", dataLen); ctrl.dataForImage = nil; ctrl.dataForImage = [NSData dataWithBytes:buff length:dataLen]; ctrl.tempImage = nil; ctrl.tempImage = [[TTImage alloc] initWithData:ctrl.dataForImage]; /* MEMORY LEAK??? */ /* These two lines causes memory leaks. I would explain it outside this code block */ [ctrl.imageVideoFrame setImage:nil]; [ctrl.imageVideoFrame setImage: ctrl.tempImage]; } else { SYS_PERROR(); } } while (dataLen &gt; 0); THREAD_EXIT: NSLog(@"pthread exit"); ctrl.isThreadRunning = NO; if (ctrl.sockFd) { simpleSocketClose(ctrl.sockFd); ctrl.sockFd = 0; } pthread_exit(NULL); } } </code></pre> <p><b>Explanation</b> of the "MEMORY LEAK???" in the code block:<br/> This line set the NSImageWell to display the image. If I continued transmitting jpeg data, I noticed that the memory of this app kept going up and would not go significantly down. I add the "= nil" trying to create an [.. release] method but this did not work. However, if I comment out these two lines, no memory leaks noticed any more (and my video function not achieved either...) </p> <p>Any suggestions? Or I should switch to non-ARC mode to examine this problem? Thanks very much!!</p> <p><b>Newer study On Jan, 25:</b><br/> I create another simple project <b>without ARC</b></p> <p>NSImage is still subclassed as TTImage (TT means TesT) as:<br/> .m file:</p> <pre><code>@implementation TTImage - (id)retain{ NSLog(@"%08x retain", (unsigned int)self); return [super retain]; } - (oneway void)release{ NSLog(@"release"); return [super release]; } - (void)dealloc{ NSLog(@"%@ deallocated.", self); return [super dealloc]; } @end </code></pre> <p>The pthread is now defined in the App delegate file:</p> <pre><code> ... // AppDelegate implementations #define AMCRelease(obj) if(obj) {[(obj) release]; (obj) = nil;} void *threadReceiveFrameData(void *arg) { @autoreleasepool { AMCAppDelegate *ctrl; NSImage *lastImage; struct sockaddr_in sockAddr; uint8_t buff[60001]; ssize_t dataLen; NSData *dataInThread = nil; TTImage *imageInThread = nil; ctrl = (AMCAppDelegate*)arg; memset (buff, 0, sizeof(buff)); ... // the same initialization as before NSLog(@"pthread init."); do { dataLen = simpleSocketReceiveFrom_udp(ctrl.sockFd, NULL, &amp;sockAddr, buff, sizeof(buff) - 1, NULL); if (dataLen &gt; 0) { printf("\n"); AMCRelease(dataInThread); dataInThread = [NSData dataWithBytes:buff length:dataLen]; NSLog(@"%d data rc: %ld", __LINE__, [dataInThread retainCount]); // Line 100 if (imageInThread) { NSLog(@"%d image pre rc: %ld", __LINE__, [imageInThread retainCount]); // Line 104 //lastImage = imageInThread; } AMCRelease(imageInThread); imageInThread = [[TTImage alloc] initWithData:dataInThread]; NSLog(@"%d data rc: %ld", __LINE__, [dataInThread retainCount]); // Line 110 NSLog(@"%d image rc: %ld", __LINE__, [imageInThread retainCount]); // Line 111 //[ctrl.imageVideoFrame setImage:nil]; [ctrl.imageVideoFrame setImage:imageInThread]; NSLog(@"%d image rc: %ld", __LINE__, [imageInThread retainCount]); // Line 115 //NSLog(@"image last rc: %ld", [lastImage retainCount]); } else { SYS_PERROR(); } } while (dataLen &gt; 0); THREAD_EXIT: AMCRelease(dataInThread); AMCRelease(imageInThread); if (ctrl.sockFd) { simpleSocketClose(ctrl.sockFd); ctrl.sockFd = 0; } pthread_exit(NULL); } } </code></pre> <p>And then I send several jpegs to the app. Here are the outputs (headers of every line ignored):</p> <pre><code>pthread init. 100 data rc: 1 110 data rc: 2 111 image rc: 1 0067d890 retain &lt;-- looks OK 115 image rc: 2 100 data rc: 1 104 image pre rc: 2 release 110 data rc: 2 111 image rc: 1 0067d890 retain &lt;-- What??? Leaks??? 0067d890 retain &lt;-- What??? 00632ba0 retain &lt;-- looks OK 115 image rc: 2 100 data rc: 1 104 image pre rc: 2 release 110 data rc: 2 111 image rc: 1 00632ba0 retain &lt;-- What??? 00632ba0 retain &lt;-- What??? 0069d580 retain 115 image rc: 2 </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload