Reputation: 1011
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 CLLocationCoordinate2D
s 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!
Upvotes: 0
Views: 147
Reputation: 6204
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:
Upvotes: 1
Reputation: 3132
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
.
Upvotes: 1