atom feed13 messages in net.java.dev.rococoa.usersRe: Invalid memory access of location...
FromSent OnAttachments
Sami NopanenNov 1, 2009 1:08 pm 
Paul LoyNov 1, 2009 2:06 pm 
Sami NopanenNov 1, 2009 2:18 pm 
Andrew ThompsonNov 1, 2009 3:25 pm 
Sami NopanenNov 1, 2009 4:12 pm 
Sami NopanenNov 6, 2009 8:43 am 
Paul LoyNov 6, 2009 9:00 am 
Sami NopanenNov 6, 2009 11:44 am 
Duncan McGregorNov 6, 2009 3:12 pm 
Andrew ThompsonNov 6, 2009 8:00 pm 
Sami NopanenNov 6, 2009 8:51 pm 
Andrew ThompsonNov 7, 2009 7:56 am 
Sami NopanenNov 7, 2009 9:07 am 
Subject:Re: Invalid memory access of location...
From:Sami Nopanen (snop@gmail.com)
Date:Nov 6, 2009 11:44:46 am
List:net.java.dev.rococoa.users

Actually, I believe I've found the problem with my original code.

The last use of the 'imageRep2' is on the line prior to 'A)'. Now, if the Java garbage collector hits in between 'A)' and 'B)', imageRep2 will get collected, causing the retain count to go down. And consequently, this will/may cause the memory area pointed to by 'pointer' to get freed, even though we still have a pointer to it. Both, adding an additional retain/release for imageRep2 seems to fix the crashing, as well as adding an additional reference to it in the end of the method, e.g. 'size = imageRep2.size()' to the second to last line.

Sami

--

private Screenshot _getScreenshot(int windowId) { NSRect nullRect = new NSRect(new NSPoint(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY), new NSSize(0, 0)); ID imageRef = QuartzLibrary.INSTANCE.CGWindowListCreateImage(nullRect, QuartzLibrary.kCGWindowListOptionIncludingWindow, windowId, QuartzLibrary.kCGWindowImageBoundsIgnoreFraming); NSBitmapImageRep imageRep = NSBitmapImageRep.CLASS.alloc().initWithCGImage(imageRef); Foundation.cfRelease(imageRef); NSSize size = imageRep2.size(); Pointer pointer = imageRep2.bitmapData(); // A) if(pointer == Pointer.NULL) return null;

int width = size.width.intValue(); int height = size.height.intValue(); int[] data = pointer.getIntArray(0, width * height); // B) return new Screenshot(width, height, data); }

On Fri, Nov 6, 2009 at 12:00 PM, Paul Loy <pa@keteracel.com> wrote:

It's a long shot, but maybe some part of the code is required to run on the main thread. I remember TIFFRepresentation needs to be run on the main thread. Maybe some part of NSBitmapImageRep requires the main thread? You could try the @RunOnMainThread annotation on the initWithCGImage method?

On Fri, Nov 6, 2009 at 4:44 PM, Sami Nopanen <snop@gmail.com> wrote:

I seem to have gotten my screenshot code to become stable. I did this by getting the bitmap data through ApplicationServices framework, instead of through NSBitmapImageRep. Unfortunately, I still don't understand why the old code did not work, so if anyone figures it out, I'd be interested.

The new code is below.

Sami

private Screenshot _getScreenshot(int windowId) { NSRect nullRect = new NSRect(new NSPoint(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY), new NSSize(0, 0));

ID imageRef = QuartzLibrary.INSTANCE.CGWindowListCreateImage(nullRect, QuartzLibrary.kCGWindowListOptionIncludingWindow, windowId, QuartzLibrary.kCGWindowImageBoundsIgnoreFraming);

long width = AppLibrary.INSTANCE.CGImageGetWidth(imageRef); long height = AppLibrary.INSTANCE.CGImageGetHeight(imageRef); long bytesPerRow = AppLibrary.INSTANCE.CGImageGetBytesPerRow(imageRef);

ID nsdataRef = AppLibrary.INSTANCE.CGDataProviderCopyData(AppLibrary.INSTANCE.CGImageGetDataProvider(imageRef)); Foundation.cfRelease(imageRef); NSData nsdata = Rococoa.wrap(nsdataRef, NSData.class, false);

byte[] data = new byte[nsdata.length()]; nsdata.getBytes(data);

return new Screenshot(width, height, bytesPerRow, data);

I get a popup of the Apple error reporting tool, with some the following dump. Also, attaching the latest version of the source I've been using for trying to isolate this. The dump is from this version.