2

I'm confused about one strange thing....I have an unsigned char array.... I allocate it using calloc and record some bytes data in it... but when I free this unsigned char and allocate it again, I see that it reserves the same address in memory which was allocated previous time. I understand why....But I cannot understand why the data that I'm trying to write there second time is not written...There is written the data that was written first time....Can anybody explain me this???????

unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));

This is how I allocate it.... Actually my problem is that because of this allocation , which happens once every 2 secs I have memory leak...But when I try to free the allocated memory sector happens thing described above....:(

Please if anybody can help me....I would be so glad... Here is the code...

- (unsigned char*) createBitmapContext:(UIImage*)anImage{

CGImageRef imageRef = [anImage CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
bytesPerPixel = 4;
bytesPerRow = bytesPerPixel * width;

NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                             bitsPerComponent, bytesPerRow, colorSpace,
                                             kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

CGContextRelease(context);

imageRef=nil;
return rawData; }

in this code there is no the part where I free(rawData), and because I cannot free it inside this method I tried to define rawData globally and free it after calling this method...but nothing interesting....

Please if anybody can help me....I would be so glad...

Garnik
  • 423
  • 1
  • 6
  • 20
  • You will need to provide a complete code fragment that shows both allocations and the buffer writes, and how you are verifying the contents. The above is not enough to answer your question. – gavinb Jun 04 '12 at 11:03
  • @gavinb done...Any interesting idea? – Garnik Jun 04 '12 at 11:21

2 Answers2

1

Ok, so this method is rendering a UIImage into a freshly allocated byte buffer and returning the buffer to the caller. Since you're allocating it with calloc, it will be initialised to 0, then overwritten with the image contents.

when I free this unsigned char and allocate it again, I see that it reserves the same address in memory which was allocated previous time

Yes, there are no guarantees about the location of the buffer in memory. Assuming you call free() on the returned memory, requesting the exact same size is quite likely to give you the same buffer back. But - how are you verifying the contents are not written over a second time? What is in the buffer?

my problem is that because of this allocation , which happens once every 2 secs I have memory leak...But when I try to free the allocated memory sector happens thing described above....:(

If there is a leak, it is likely in the code that calls this method, since there is no obvious leakage here. The semantics are obviously such that the caller is responsible for freeing the buffer. So how is that done?

Also, are you verifying that the CGBitmapContext is being correctly created? It is possible that some creation flags or parameters may result in an error. So add a check for context being valid (at least not nil). That could explain why the content is not being overwritten.

One easy way to ensure your memory is being freshly updated is to write your own data to it. You could fill the buffer with a counter, and verify this outside the method. For example, just before you return rawData:

static unsigned updateCounter = 0;
memset(rawData, updateCounter & 0xff, width*height*4);

This will cycle through writing 0-255 into the buffer, which you can easily verify.

Another thing - what are you trying to achieve with this code? There might be an easier way to achieve what you're trying to achieve. Returning bare buffers devoid of metadata is not necessarily the best way to manage your images.

gavinb
  • 19,278
  • 3
  • 45
  • 60
  • The aim of my project is to write screensharing tool. Using this method I want to get pixel colors and compare with previous picture for similarity. Then in other method's I get the difference of those 2 pics and send changed part.All these parts are done but I'm having this leak. I'm sure in context because I get next picture every time. And also I have tried to set memory to zero memset(rawData,0,weight*height*4); after I free it, but still the same. I understand why it returns the same address everytime, but I cannot understand why CGBitmapContextCreate method doesn't overwrite data inside. – Garnik Jun 04 '12 at 13:07
  • And also I'm sure that the leak is in allocation of rawData...Have checked in hundred ways... – Garnik Jun 04 '12 at 13:10
  • yeah I know the param order...but this won't help me – Garnik Jun 04 '12 at 13:51
  • Have you verified the context is correctly created, ie. context is not nil? As mentioned above in the answer, if the flags are not all valid, you may not get a valid context. Then the drawing will not succeed and not overwrite the data. – gavinb Jun 04 '12 at 13:51
  • Ok, some more details are needed then. How did you verify the `CGBitmapContext` is always valid? And how did you verify that the leak is in the allocation of `rawData`? Can you post the code that calls `createBitmapContext:`? If there's a leak, it must be in the caller's logic, as ownership of the memory is passed out. – gavinb Jun 04 '12 at 21:49
  • The part where i call createBitmapContext is in above code...also in there I allocate the rawData and when i free it in this method the leak is disappeared. also it allocatess 3Mb per sec and the size of rawData is 3.145.786 bytes=3Mb so these many other tests let me assume that leak is from there... – Garnik Jun 05 '12 at 12:27
  • I'm referring to the other code that calls *your* `createBitmapContext:` method above (not `CGBitmapContextCreate` above). The caller of the code you posted is likely doing leaking, since it is the owner of the allocated memory. So it's hard to figure out how it's leaking without seeing more code. – gavinb Jun 05 '12 at 12:35
0

So guys I solved this issue...First thing I've changed createBitmapContext method to this

- (void) createBitmapContext:(UIImage*)anImage andRawData:(unsigned char *)theRawData{

CGImageRef imageRef = [anImage CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
//    unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
bytesPerPixel = 4;
bytesPerRow = bytesPerPixel * width;

NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(theRawData, width, height,
                                             bitsPerComponent, bytesPerRow, colorSpace,
                                             kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

CGContextRelease(context);
imageRef=nil;
//    return theRawData;}

then...besides this I missed the part where I assign newRawData to oldRawData and by this I was having two pointers to the same memory address...So from here came the issue... I changed this assignment part to this memcpy(rawDataForOldImage, rawDataForNewImage,newCapturedImage.size.width*newCapturedImage.size.height*4); and here the problem is solved....Thanks to all

Garnik
  • 423
  • 1
  • 6
  • 20