PDA

View Full Version : Getting a bad access code in xcode




31rhcp
Aug 17, 2013, 03:49 PM
I am trying to compile a file for a MOOC that I am taking. Without going into details, the program has to read 1000000 long ints into an array. The program works very well with smaller array lengths, but it gives me an issue here. I get a Thread 1: EXC_BAD_ACCESS (code=2,address=0x7fff5eca9ba8) error in Xcode.

Any ideas on how to fix this?

#define LEN 999999
int x = 0;

file = fopen("address to the location on my comp", "r");
if (file == NULL)
{
printf("File not found!\n");
}
long int arr[LEN];
long int sorted[LEN];
long int temp;
int found[20001] = { 0 };
for (int x = 0; (x < LEN + 1) && !feof(file); x++)
{
fscanf(file, "%ld", &temp);
arr[x] = temp;
}
fclose(file);



subsonix
Aug 17, 2013, 04:06 PM
for (int x = 0; (x < LEN + 1) && !feof(file); x++)



This looks like a fence post error, that is, your array is declared as being size LEN but since and array is indexed from 0, LEN + 1 is one over.

Edit: also watch out for using feof in the loop like that, it's only set once eof is read, which is one read too many. You can actually use fscanf directly in the loop condition since it returns the amount of items read, in your case that's 1, or 0 if there is no more to read.

31rhcp
Aug 17, 2013, 10:59 PM
This looks like a fence post error, that is, your array is declared as being size LEN but since and array is indexed from 0, LEN + 1 is one over.



You are correct there is a fence post error there. However, I found that the solution is how I allocated the array. Dynamic allocation solved my problem.

long* arr = new long[LEN];

subsonix
Aug 17, 2013, 11:03 PM
You are correct there is a fence post error there. However, I found that the solution is how I allocated the array. Dynamic allocation solved my problem.

long* arr = new long[LEN];

Ok I see, so you used it in a different scope not shown in the snippet above?

31rhcp
Aug 18, 2013, 08:24 AM
Ok I see, so you used it in a different scope not shown in the snippet above?

The program was an assignment for a MOOC I was taking. I had to find out how many integers in the range [-10000 to 10000] had at least one pair of numbers in a given 1000000 integer array that summed to them.

So basically, all 1000000 integers are read into the array arr[] and then sorted into sorted[] for searching purposes later on. sorted[] gets passed around a lot, but arr[] is only used here.

Hopefully that answers your question. I'm just a novice. Xcode was giving me the error at the line

file = fopen("address to the location on my comp", "r");

so I assumed the file IO/array storage was the issue.

Sander
Aug 20, 2013, 04:13 AM
long* arr = new long[LEN];

Is this a MOOC about C++? In my humble opinion, the first class should explain never to use "new".

ElectricSheep
Aug 20, 2013, 12:04 PM
Off-by-one errors aside, the reason why your program worked well with smaller array lengths but failed with larger lengths is due to limitations on how large the stack can grow. On Mac OS X, the default stack limit is around 8 megs, with a hard upper limit of 65 megs. Just a single stack-allocated array of a million long ints is going to consume most of your stack space, and you are going to find yourself running into problems very quickly.

This is a case where use of new to allocate on the heap is advisable. However, you really shouldn't use raw pointers as the onus is upon you track ownership and delete them when finished. Instead, leverage something like a unique_ptr:


#include <memory>
...

std::unique_ptr<long int[]> arr(new long int[LEN]);
std::unique_ptr<long int[]> sorted(new long int[LEN]);

...


The array is allocated on the heap, but you get the benefit of the management of automatic variables; once arr goes out of scope, the array will be deleted.

Irfin
Aug 21, 2013, 10:26 PM
I think the LEN declaration is also not sufficient for storing 1000000 elements. LEN should declared to 1000000 not 999999. By declaring LEN as:
#define LEN 999999

And then doing:
long int arr[LEN];

Means you will have array variable which can hold 999999 long int values, ranged from index 0 to 999998.

or even:
long * arr = new long[LEN];
will also declare a pointer which points to some memory area which can hold up to 999999 long int values, not 1000000 long int values.

So should change LEN declaration to #define LEN 1000000;