C memory management with 2D arrays - objective-c
I'm starting to play around with some C code within Objective-C programs. The function I'm trying to write sorts all of the lat/long coordinates from a KML file into clusters based on 2D arrays.
I'm using three 2D arrays to accomplish this:
NSUInteger **bucketCounts refers to the number of CLLocationCoordinate2Ds in a cluster.
CLLocationCoorindate2D **coordBuckets is an array of arrays of coordinates
NSUInteger **bucketPointers refers to an index in the array of coordinates from coordBuckets
Here's the code that is messing me up:
//Initialize C arrays and indexes
int n = 10;
bucketCounts = (NSUInteger**)malloc(sizeof(NSUInteger*)*n);
bucketPointers = (NSUInteger**)malloc(sizeof(NSUInteger*)*n);
coordBuckets = (CLLocationCoordinate2D **)malloc(sizeof(CLLocationCoordinate2D*)*n);
for (int i = 0; i < n; i++) {
bucketPointers[i] = malloc(sizeof(NSUInteger)*n);
bucketCounts[i] = malloc(sizeof(NSUInteger)*n);
}
NSUInteger nextEmptyBucketIndex = 0;
int bucketMax = 500;
Then for each CLLocationCoordinate2D that needs to be added:
//find location to enter point in matrix
int latIndex = (int)(n * (oneCoord.latitude - minLat)/(maxLat-minLat));
int lonIndex = (int)(n * (oneCoord.longitude - minLon)/(maxLon-minLon));
//see if necessary bucket exists yet. If not, create it.
NSUInteger positionInBucket = bucketCounts[latIndex][lonIndex];
if (positionInBucket == 0) {
coordBuckets[nextEmptyBucketIndex] = malloc(sizeof(CLLocationCoordinate2D) * bucketMax);
bucketPointers[latIndex][lonIndex] = nextEmptyBucketIndex;
nextEmptyBucketIndex++;
}
//Insert point in bucket.
NSUInteger bucketIndex = bucketPointers[latIndex][lonIndex];
CLLocationCoordinate2D *bucketForInsert = coordBuckets[bucketIndex];
bucketForInsert[positionInBucket] = oneCoord;
bucketCounts[latIndex][lonIndex]++;
positionInBucket++;
//If bucket is full, expand it.
if (positionInBucket % bucketMax == 0) {
coordBuckets[bucketIndex] = realloc(coordBuckets[bucketIndex], (sizeof(CLLocationCoordinate2D) * (positionInBucket + bucketMax)));
}
Things seem to be going well for about 800 coordinates, but at the same point a value in either bucketCounts or bucketPointers gets set to an impossibly high number, which causes a reference to a bad value and crashes the program. I'm sure this is a memory management issue, but I don't know C well enough to troubleshoot it myself. Any helpful pointers for where I'm going wrong? Thanks!
It seems to me each entry in bucketPointers can potentially have its own "bucket", requiring a unique element of coordBuckets to hold the pointer to that bucket.
The entries in bucketPointers are indexed by bucketPointers[latIndex][lonIndex], so there can be n*n of them, but you allocated only n places in coordBuckets.
I think you should allocate for n*n elements in coordBuckets.
Two problems I see:
You don't initialize bucketCounts[] in the given code. It may well happen to all 0s but you should still initialize it with calloc() or memset():
bucketCounts[i] = calloc(n, sizeof(NSUInteger));
if oneCoord.latitude == maxLat then latIndex == n which will overflow your arrays which have valid indexes from 0 to n-1. Same issue with lonIndex. Either allocate n+1 elements and/or make sure latIndex and lonIndex are clamped from 0 to n-1.
In code using raw arrays like this you can solve a lot of issues with two simple rules:
Initialize all arrays (even if you technically don't need to).
Check/verify all array indexes to prevent out-of-bounds accesses.
Related
Looping with iterator vs temp object gives different result graphically (Libgdx/Java)
I've got a particle "engine" whom I've implementing a Pool system to and I've tested two different ways of rendering every Particle in a list. Please note that the Pooling really doesn't have anything with the problem to do. I just followed a tutorial and tried to use the second method when I noticed that they behaved differently. The first way: for (int i = 0; i < particleList.size(); i++) { Iterator<Particle> it = particleList.iterator(); while (it.hasNext()) { Particle p = it.next(); if (p.isDead()){ it.remove(); } p.render(batch, delta); } } Which works just fine. My particles are sharp and they move with the correct speed. The second way: Particle p; for (int i = 0; i < particleList.size(); i++) { p = particleList.get(i); p.render(batch, delta); if (p.isDead()) { particleList.remove(i); bulletPool.free(p); } } Which makes all my particles blurry and moving really slow! The render method for my particles look like this: public void render(SpriteBatch batch, float delta) { sprite.setX(sprite.getX() + (dx * speed) * delta * Assets.FPS); sprite.setY(sprite.getY() + (dy * speed) * delta * Assets.FPS); ttl--; sprite.setScale(sprite.getScaleX() - 0.002f); if (ttl <= 0 || sprite.getScaleX() <= 0) isDead = true; sprite.draw(batch); } Why do the different rendering methods provide different results? Thanks in advance
You are mutating (removing elements from) a list while iterating over it. This is a classic way to make a mess. The Iterator must have code to handle the delete case correctly. But your index-based for loop does not. Specifically when you call particleList.remove(i) the i is now "out of sync" with the content of the list. Consider what happens when you remove the element at index 3: 'i' will increment to 4, but the old element 4 got shuffled down into index 3, so it will get skipped. I assume you're avoiding the Iterator to avoid memory allocations. So, one way to side-step this issue is to reverse the loop (go from particleList.size() down to 0). Alternatively, you can only increment i for non-dead particles.
Changing content of a matrix in c
How do you change just part of a matrix in c (I'm actually in Objective-C, but using matrices in c). For example: NSInteger tempMapMatrix[100][100] = {{0,0,1,1,2,2,1,1,0,2,4,4,4,0,0,1,2,2,1,0,0,0,0,0,0}, {0,1,1,2,3,2,1,1,4,4,3,4,4,0,0,1,2,2,1,0,0,0,0,0,0}, {1,1,2,3,3,2,1,4,1,3,3,4,4,0,0,1,2,2,1,0,0,0,0,0,0}, {1,1,3,3,3,2,4,1,1,1,4,4,4,0,0,1,2,2,1,0,0,0,0,0,0}, {0,1,1,2,2,2,4,4,4,4,4,4,4,0,0,1,1,1,1,0,0,0,4,4,0}, {0,0,1,1,2,2,1,0,0,2,3,4,4,0,0,0,0,0,0,0,0,0,4,4,0}, {4,4,1,1,2,2,1,1,0,1,1,0,4,0,0,0,0,0,0,0,0,0,4,4,4}, {0,4,1,2,2,2,1,1,0,4,4,4,4,4,4,4,0,0,0,0,1,0,0,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,4,0,3,3,3,3,3,3,3,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,4,4,3,2,2,2,2,2,3,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,4,4,3,2,3,3,3,2,3,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,4,4,3,2,3,2,2,2,3,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,4,3,3,2,3,2,3,3,3,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,4,4,1,2,2,3,2,0,0,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,4,3,3,3,3,3,0,0,0,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,4,4,0,0,0,0,0,0,0,0,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,0,1,0,0,0,0,0,0,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,0,1,0,0,0,1,1,1,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,1,0,0,0,0,0,1,1,0,0}, {0,0,1,2,2,2,1,0,0,0,4,4,4,0,0,1,1,0,0,0,0,0,1,0,0}}; then I want to change the first couple (x and y) of integers: tempMapMatrix[100][100] = {{5,5,5,5,5,1,2,3}, {5,5,5,5,5,1,2,3}, {5,5,1,1,1,1,2,3}, {5,5,1,5,5,1,2,3}, {5,5,1,1,1,1,2,3}, {5,5,5,5,5,5,5,5}, {5,5,5,5,5,1,2,3}, {5,2,2,2,5,1,2,3}, {5,2,5,2,5,1,2,3}, {5,2,2,2,5,1,2,3}}; but I'm getting an error (Expected Expression). I've tried tempMapArray = stuff; tempMapArray[][] = stuff; but none work. Any way to change the first couple of ints in the matrix?
You need to iterate over them, this is C, you don't have syntactic sugar to assingn pieces of arrays like you want. If you want to change, for example, every first element of each row you could do something like: for (int = 0; i < 100; ++i) { tempMatrix[i][0] = 5; } so for the first couple of every row you should do for (int = 0; i < 100; ++i) { tempMatrix[i][0] = 5; tempMatrix[i][1] = 5; } and so on.
You have to access and change each element in the matrix individually. I.e.: tempMapMatrix[0][0] = 5; tempMapMatrix[0][1] = //... There is no way to "batch change" the contents of an array (one-dimensional or n-dimensional) in C. The easiest way to achieve this effect is to write a for-loop and iterate over the contents of the two dimensional array and insert the required values in the required places.
Realloc not expanding my array
I'm having trouble implementing realloc in a very basic way. I'm trying to expand the region of memory at **ret, which is pointing to an array of structs with ret = realloc(ret, newsize); and based on my debug strings I know newsize is correctly increasing over the course of the loop (going from the original size of 4 to 8 to 12 etc.), but when I do sizeof(ptr) it's still returning the original size of 4, and the things I'm trying to place into the newly allocated space can't be found (I think I've narrowed it down to realloc() which is why I'm formatting the question like this) I can post the function in it's entirety if the problem isn't immediately evident to you, I'm just trying to not "cheat" with my homework too much (the code is kind of messy right now anyway, with heavy use of printf() for debug). [EDIT] Alright, so based on your answers I'm failing at debugging my code, so I guess I'll post the whole function so you can tell me more about what I'm doing wrong. (You can ignore the printf()'s since most of that is debug that isn't even working) Booking **bookingSelectPaid(Booking **booking) { Booking **ret = malloc(sizeof(Booking*)); printf("Initial address of ret = %p\n", ret); size_t i = 0; int numOfPaid = 0; while (booking[i] != NULL) { if (booking[i]->paid == 1) { printf("Paying customer! sizeof(Booking*) = %d\n", (int)sizeof(Booking*)); ++numOfPaid; size_t newsize = sizeof(Booking*) * (numOfPaid + 1); printf("Newsize = %d\n", (int)newsize); Booking **temp = realloc(NULL, (size_t)newsize); if (temp != NULL) printf("Expansion success! => %p sizeof(new pointer) = %d ret = %p\n", temp, (int)sizeof(temp), ret); ret = realloc(ret, newsize); ret[i] = booking[i]; ret[i+1] = NULL; } ++i; printf("Sizeof(ret) = %d numOfPaid = %d\n", (int)sizeof(ret), numOfPaid); } return ret; } [EDIT2] --> http://pastebin.com/xjzUBmPg [EDIT3] Just to be clear, the printf's, the temp pointer and things of that nature are debug, and not part of the intended functionality. The line that is puzzling me is either the one with realloc(ret, newsize); or ret[i] = booking[i] Basically I know for sure that booking contains a table of structs that ends in NULL, and I'm trying to bring the ones that have a specific value set to 1 (paid) onto the new table, which is what my main() is trying to get from this function... So where am I going wrong?
I think the problem here is that your sizeof(ptr) only returns the size of the pointer, which will depend on your architecture (you say 4, so that would mean you're running a 32-bit system). If you allocate memory dynamically, you have to keep track of its size yourself.
Because sizeof(ptr) returns the size of the pointer, not the allocated size
Yep, sizeof(ptr) is a constant. As the other answer says, depends on the architecture. On a 32 bit architecture it will be 4 and on a 64 bit architecture it will be 8. If you need more help with questions like that this homework help web site can be great for you. Good luck.
How to return a C-array from method in Objective-C?
I have a function that returns a variable and I want to know how to return an array the issue is it isn't an NSArray it is just an average C array like this... -(b2Fixture*) addFixturesToBody:(b2Body*)body forShapeName:(NSString*)shape { BodyDef *so = [shapeObjects objectForKey:shape]; assert(so); FixtureDef *fix = so->fixtures; int count = -1; b2Fixture *Fixi[4]; while(fix) { count++; NSLog(#"count = %d",count); Fixi[count]= body->CreateFixture(&fix->fixture); if (Fixi[count]!=0) { NSLog(#"Fixi %d is not 0",count); } if (body->CreateFixture(&fix->fixture)!=0) { NSLog(#"body %d is not 0",count); } fix = fix->next; } return *Fixi; } If you see some variable types you don't know it's because I'm using cocos2d framework to make a game but I'm returning a variable of b2Fixture... This code compiles however only saves the value of the first block of the array "fixi[0]" not the whole array like I want to pass anyhelp :) thankyou
You can't return a local array. You'll need to do some kind of dynamic allocation or pull a trick like having the array inside a structure. Here is a link to an in-depth article that should help you out.
In general returning C arrays by value is a bad idea, as arrays can be very large. Objective-C arrays are by-reference types - they are dynamically allocated and a reference, which is small, is what is passed around. You can dynamically allocate C arrays as well, using one of the malloc family for allocation and free for deallocation. You can pass C structures around by value, and this is common, as in general structures tend to be small (or smallish anyway). Now in your case you are using a small array, it has just 4 elements. If you consider passing these 4 values around by value is reasonable and a good fit for your design then you can do so simply by embedding the C array in a C structure: typedef struct { b2Fixture *elements[4]; } b2FixtureArray; ... -(b2FixtureArray) addFixturesToBody:(b2Body*)body forShapeName:(NSString*)shape { BodyDef *so = [shapeObjects objectForKey:shape]; assert(so); FixtureDef *fix = so->fixtures; int count = -1; b2FixtureArray Fixi; while(fix) { count++; NSLog(#"count = %d", count); Fixi.elements[count]= body->CreateFixture(&fix->fixture); if (Fixi.elements[count] != 0) { NSLog(#"Fixi %d is not 0",count); } if (body->CreateFixture(&fix->fixture) != 0) { NSLog(#"body %d is not 0", count); } fix = fix->next; } return Fixi; } ... // sample call outline b2FixtureArray result = [self addFixturesToBody...] Whether this standard C "trick" for passing arrays by value is appropriate for your case you'll have to decide. Note: If b2fixture is an Objective-C object make sure you understand the memory management implications of having a C array of objects references depending on the memory management model (MRC, ARC, GC) you are using.
If you need to design function or method that has to return a fixed or limited size array, one possibility is to pass a pointer to the result array to the function or method as a parameter. Then the caller can take care of allocating space, or just use a local or instance variable array. You might want the called function to sanity check that the array parameter isn't NULL before using the array.
Maximum index size for array
The following code is crashing my program. I found the problem is the size of the array. If I reduce the size to 320*320, it works fine. Does it make sense that this wound be a limitation? If so, what is a work around? I am coding in Objective C for IPhone. Any help would be appreciated. Thanks! int life_matrix[320*350]; x_size=320; y_size=350; for (int counter=0; counter < x_size; counter++) { for (int counter2=0;counter2 < (y_size); counter2++) { life_matrix[counter*(int)x_size+counter2] = rand()%2; } }
The array is allocated on stack and usually the stack size is limited. If you need a big array, usually it is a good idea to allocate it on heap.
leiz's advice is correct, you really should be allocating this dynamically otherwise you run the risk of running into a situation were the size of the array is larger than the available memory on the stack. Also the formula you are using to map a 2-dimensional grid to a 1-dimensional array is incorrect. You should be multiplying by y_size instead of x_size. life_matrix[counter*(int)y_size+counter2] = rand()%2; or you could flip your counters life_matrix[counter2*(int)x_size+counter] = rand()%2; Another approach to solving this would be to use it as a 1-dimensional array for initialization: for(int n = 0; n < x_size * y_size; ++n) { life_matrix[n] = rand()%2; }