memset error in iPad app - objective-c

Hi Im currently building an iPad app. I was using the memset() as below but every tine it runs I get a bad access error?
arrayPointer = malloc(sizeof(int) * size);
memset(arrayPointer, 0, sizeof(int)* size); //sets all the values in the array to 0
Cheers

You could use calloc() it basically does the same as malloc() but also sets all bits to 0 in the allocated memory. It is also suited well for array initializations. For your example:
arrayPointer = calloc(sizeof(int), size);
EDIT: You should consider inspecting the returned pointer. NULL will be returned, when your memory allocation was erroneous.

Related

Expanding an array within a structure in C

I've got a question about what I think boils down to C syntax and memory considerations. I have a callback in an Objective-C class that processes some audio, and one of the arguments is bufferListInOut. It represents a mono audio signal that I'd like to convert to stereo. Here's my code:
static void tap_ProcessCallback(MTAudioProcessingTapRef tap,
CMItemCount numberFrames,
MTAudioProcessingTapFlags flags,
AudioBufferList *bufferListInOut,
CMItemCount *numberFramesOut,
MTAudioProcessingTapFlags *flagsOut){
// Retrieve mono audio data into bufferListInOut
MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, NULL, NULL, NULL);
// Copy the mono channel's data
float *channelLeft = malloc(numberFrames * sizeof(float));
channelLeft = bufferListInOut->mBuffers[0].mData;
// Attempt to create a second channel which is (currently) a copy of the first
bufferListInOut->mNumberBuffers = 2; // 2 for stereo, 1 for mono
bufferListInOut->mBuffers[1].mNumberChannels = 1;
bufferListInOut->mBuffers[1].mDataByteSize = numberFrames * sizeof(Float32);
bufferListInOut->mBuffers[1].mData = channelLeft;
// Set number of frames out
*numberFramesOut = numberFrames;
}
Some notes:
In this code, the new channel is just a copy of the original, but in practice it will undergo some processing.
The naming is a little weird, but mNumberBuffers is indeed meant to be 2 and mNumberChannels is meant to be 1.
This crashes with an EXC_BAD_ACCESS error on a rendering thread down the line. So, my question is what is the right way to add a new buffer to this struct? I don't delve into C too often, so I'm sure I'm missing some basics here. Any pointers on this would be great. Thanks for reading.
You cannot do what you are attempting, at least in the way you are trying to do it. The type AudioBufferList is declared as:
struct AudioBufferList { UInt32 mNumberBuffers; AudioBuffer mBuffers[1]; };
This is a classic C pattern for a variable sized struct. To create a struct for N buffers a single block of memory is allocated with the size:
sizeof(UInt32) + N * sizeof(AudioBuffer)
The address of that block is assigned to a AudioBufferList * variable and the field mNumberBuffers set to N. You cannot simply increase the mNumberBuffers to increase the size of the array, instead you must either allocate a new complete struct, or realloc the existing one - realloc increases the size of memory block if possible or allocates a new one and copies the existing data into it if not.
Given your tap_ProcessCallback() function is passed a AudioBuuferList * value and does not return one, there is no way it can change the size of the struct (i.e. the number of buffers) it is passed.
As pointed out in comments you are also doing pointer assignment when you intend to copy memory - see memcpy and friends.
So you need a redesign - your goal is possible, just not how and where you've attempted it.
HTH

Reducing peak memory consumption

I generate bitmaps using the next simplified for the sake of simplicity code:
for (int frameIndex = 0; frameIndex < 90; frameIndex++) {
UIGraphicsBeginImageContextWithOptions(CGSizeMake(130, 130));
// Making some rendering on the context.
// Save the current snapshot from the context.
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
[self.snapshots addObject:snapshot];
UIGraphicsEndImageContext();
}
So nothing non-trivial but everything gets complicated when an operating system gives about 30 MB of memory for everything (in this particular case it is watch OS 2 but nevertheless it is not the OS-dependent question) and by exceeding the quota, the OS just kills the application's process.
The next graph from the Allocations Instrument illustrates the question:
It is the same graph but with different annotations of memory consumption - before, at the moment and after the aforementioned code execution. As it can be seen about 5.7 MB of bitmaps have been generated eventually and it is the absolutely acceptable result. What is not acceptable it is memory consumption (44.6 MB) at the peak of the graph - all of this memory is eaten by CoreUI: image data. Given the fact that the action takes place in a background thread the time of execution is not that important.
So the questions: What is the right approach to decreasing memory consumption (maybe by increasing the execution time) to fit the memory quota and why the memory consumption is increased despite UIGraphicsEndImageContext is called?
Update 1:
I think splitting the whole operation by using NSOperation, NSTimer etc. will do the trick but still trying to come up with some synchronous solution.
Tried to gather all answers together and tested the next piece of code:
UIGraphicsBeginImageContextWithOptions(CGSizeMake(130, 130));
for (int frameIndex = 0; frameIndex < 45; frameIndex++) {
// Making some rendering on the context.
#autoreleasepool {
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
[self.snapshots addObject:snapshot];
}
CGContextClearRect(UIGraphicsGetCurrentContext(), CGSizeMake(130, 130));
}
for (int frameIndex = 0; frameIndex < 45; frameIndex++) {
// Making some rendering on the context.
#autoreleasepool {
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
[self.snapshots addObject:snapshot];
}
CGContextClearRect(UIGraphicsGetCurrentContext(), CGSizeMake(130, 130));
}
UIGraphicsEndImageContext();
What has changed:
Split 90 iterations into 2 parts of 45.
Moved a graphic context outside and clear it after each iteration instead of creating new one.
Wrapped taking and storing snapshots in the autorelease pool.
As a result - nothing changed, memory consumption remains on the same level.
Also, if remove taking and storing a snapshot at all it will decrease memory consumption only for 4 MB i.e. less than 10%.
Update 2:
Doing rendering by a timer every 3 seconds generates the next graph:
As you see memory is not freed (to be precise - not fully) even if rendering is divided by time intervals. Something tells me that memory is not freed until the object that performs rendering exists.
Update 3:
The problem has been solved by combining 3 approaches:
Splitting the whole rendering task into subtasks. For example, 90 drawings are split into 6 subtasks by 15 drawings in each (The number of 15 was found empirically).
Executing all subtasks serially using dispatch_after with the small interval after each (0.05s in my case).
And the last and the most important. To avoid the memory leak like on the last graph - each subtask should be executed in a context of a new object. For example:
self.snapshots = [[SnaphotRender new] renderSnapshotsInRange:[0, 15]];
Thanks to everyone for answering but #EmilioPelaez was closest to the right answer.
Corrected the to the updated question frame count.
The total byte size of the images could be 130 * 130 * 4 (bytes per pixel) * 90 = ~6MB.
Not to sure about the watch but temporary memory might be building up, you could try wrapping the snap shot code in an #autoreleasepool block:
#autoreleasepool {
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
[self.snapshots addObject:snapshot];
}
I think your problem is that you are doing all the snapshots in the same context (the context the for loop is in). I believe the memory is not being released until the context ends, which is when the graph goes down.
I would suggest you reduce the scope of the context, so instead of using a for loop to draw all frames you would keep track of the progress with some iVars and draw just one frame; whenever you finish rendering the frame, you can call the function again with a dispatch_after and modify the variables. Even if the delay is 0, it will allow the context to end and clean up the memory that is no longer being used.
PS. When I mean context I don't mean a graphics context, I mean a certain scope in your code.
wait, image resolution plays a big role, for example, a one mega byte jpeg image of the dimensions 5000 px * 3000 px would consume ram of size of 60 MB, 5000*3000*4 bytes are 60 MB, images get decompressed into the ram, so let's troubleshoot, so first, please tell us what kind of image sizes (dimensions) do you use ?
Edit (after clarifications):
I think, that the proper way should be not to store UIImage objects directly, but compressed NSData objects (i.e. using
UIImageJPEGRepresentation). And then, when need it, convert them again to UIImage objects.
However, if you use many of them simultaneously, you're going to run out memory quite rapidly.
Original answer:
Actually the total size can be higher than 10MB (probably > 20MB) depending on the scaling factor (as seen here). Note that the UIGraphicsBeginImageContextWithOptions requires a scale parameter in contrast to the UIGraphicsBeginImageContext. So my guess it's this is somehow related to a screenshot isn't it?
Also the method UIGraphicsGetImageFromCurrentImageContext it's thread safe, so it might be returning a copy or using more memory. Then you have your 40MB.
This answer states that iOS somehow stores the images compressed when not displayed. This can be the reason to the 6MB of usage afterwards.
My final guess is that the device is detecting a peak of memory and then tries to save memory somehow. Since the images are not being used, it compressed them internally and recycles memory.
So I wouldn't worry because it looks like it's taking care of it by itself. But then you can do as others have suggested, save the image into a file and don't keep it in memory if you're not going to use it.

What is the meaning of "float *newAudio"

Sorry for my newbie question. Please refrain from down voting me because I am learning C. I am an experienced programmer on other languages, but not on C. I am trying to learn C at the same time I am trying to understand a library for iOS called Novaine, on Github.
This library has a module with the following signature:
Novocaine *audioManager = [Novocaine audioManager];
[audioManager setInputBlock:^(float *newAudio, UInt32 numSamples, UInt32 numChannels) {
}];
So, the internal block is receiving numSamples, numChannels and newAudio and newAudio is of kind float pointer?
What kind of object is this? an array of floats? if this is an array, how do I access its values? How do I know the number of elements it has?
This is a pointer to float value. Nothing strange here. It is often use to point some area in memory. You don't know the size of this are. Might be a single float but also can be larger, continuous space in memory.
You don't know what type of object is stored there. float doesn't mean that floats are stored there. It could be declared as void * as well. Again, it is just a space in memory. By typing float * you just give the compile a hint that when you move newAudio pointer (doing or example newAudio ++) it will move a pointer by a sizeof(float) number of bytes.
Based on method fingerprint I assume that this is a pointer to the first element of some buffer which size is probably numSamples * numChannels * size of single sample
This part of memory should be allocated first, to make sure that it's reserved for you:
float *newAudio = calloc(numSamples * numChannels, sizeof(float));

Getting size of a pointer after memory allocation

I've been reading about sizeof, malloc, and malloc_size, but for some reason I cannot get it to work properly in objective c.
What I'm trying to do is to dynamically allocate memory and then check the size of the pointer.
I tried doing this:
void *pointer = malloc( sizeof(void) * 8 );
long test1 = malloc_size(pointer); // Its value is 16
long test2 = sizeof(pointer); // Its value is 8
The link below answer exactly the same question but it doesn't work for me.
EDIT:
I also tried using
char *malloc( sizeof(char) * 8)
but it didn't work either.
malloc_size is returning the correct answer - malloc returns a block of at least the size you request, but it may be (a little) larger. This is just a facet of the way dynamic memory is managed, it parallels the way disk files are made up of allocation blocks. A quick test on 64-bit Intel suggests malloc's allocation unit is probably 16 bytes.
pointer is of type of *, so no matter what memory is malloced to pointer, sizeof(pointer) should be fixed value, it's 4 (32bit sys) or 8 (64bit sys).

Struct Pointer Not Providing the Correct Size in sizeof() method

I'm having a issue getting the size of a struct pointer after allocating the memory using malloc or realloc. I've worked around this by keeping track of the memory in a separate counter, but I would like to know if this is a bug or if there is a way to properly query the size of a struct pointer.
Sample code demonstrates that no matter how much memory I allocate to the struct pointer it always returns 4 when querying using the sizeof() method.
typedef struct {
int modelID;
int bufferPosition;
int bufferSize;
} Model;
Model *models = malloc(10000 * sizeof(Model));
NSLog(#"sizeof(models) = %lu", sizeof(models)); //this prints: sizeof(models) = 4
4 is the correct answer, because "models" is a pointer, and pointers are 4 bytes. You will not be able to find the length of an array this way. Any reason you're not using NSArray?
If I understand you correctly you want to get at the size of the allocated buffer.
sizeof if the wrong way to go since it is evaluated at compile time. The size of the buffer is a runtime concept.
You would need a way to query you C library to return the allocation size for the pointer to the buffer.
Some systems have a way to get that kind of information, for instance malloc_size on Mac OS.
4 is the correct answer.
Pointers point to a memory location which could contain anything. When you are querying the size of a pointer, it gives the size of the memory location which holds the pointer, which in your case is 4.
For example
int *a = pointing to some large number;
int *b = pointing to a single digit number;
In the above case, both a and b have the same size irrespective of where they are pointing to.
For more information, have a look at this post size of a pointer
sizeof(myvar) will return size of pointer. in 32bit environment it equals to 4(bytes).
why don't you use sizeof (Model) instead?