views:

128

answers:

6

Hi guys, I'm taking a class on C, and running into a segmentation fault. From what I understand, seg faults are supposed to occur when you're accessing memory that hasn't been allocated, or otherwise outside the bounds. 'Course all I'm trying to do is initialize an array (though rather large at that)

Am I simply misunderstanding how to parse a 2d array? Misplacing a bound is exactly what would cause a seg fault-- am I wrong in using a nested for-loop for this?

The professor provided the clock functions, so I'm hoping that's not the problem. I'm running this code in Cygwin, could that be the problem? Source code follows. Using c99 standard as well.

To be perfectly clear: I am looking for help understanding (and eventually fixing) the reason my code produces a seg fault.

#include <stdio.h>
#include <time.h>
int main(void){
   //first define the array and two doubles to count elapsed seconds.   
   double rowMajor, colMajor;
   rowMajor = colMajor = 0;
   int majorArray [1000][1000] = {};

   clock_t start, end;

   //set it up to perform the test 100 times.
   for(int k = 0; k<10; k++)
   {
   start=clock();
   //first we do row major
   for(int i = 0; i < 1000; i++)
   {
       for(int j = 0; j<1000; j++)
       {
           majorArray[i][j] = 314;
       }
   }
   end=clock();
   rowMajor+= (end-start)/(double)CLOCKS_PER_SEC;
   //at this point, we've only done rowMajor, so elapsed = rowMajor
   start=clock();
   //now we do column major
     for(int i = 0; i < 1000; i++)
   {
       for(int j = 0; j<1000; j++)
       {
           majorArray[j][i] = 314;
       }
   }
   end=clock();
   colMajor += (end-start)/(double)CLOCKS_PER_SEC;
   }
   //now that we've done the calculations 100 times, we can compare the values.
   printf("Row major took %f seconds\n", rowMajor);
   printf("Column major took %f seconds\n", colMajor);
   if(rowMajor<colMajor)
   {
     printf("Row major is faster\n");
   }
   else
   {
      printf("Column major is faster\n");
   }

   return 0;

}
A: 

This code runs fine for me under Linux and I can't see anything obviously wrong about it. You can try to debug it via gdb. Compile it like this:

gcc -g -o testcode test.c

and then say

gdb ./testcode

and in gdb say run

If it crashes, say where and gdb tells you, where the crash occurred. Then you now in which line the error is.

fschmitt
+5  A: 

You are trying to grab 1000 * 1000 * sizeof( int ) bytes on the stack. This is more then your OS allows for the stack growth. If on any Unix - check the ulimit -a for max stack size of the process.

As a rule of thumb - allocate big structures on the heap with malloc(3). Or use static arrays - outside of scope of any function.

In this case, you can replace the declaration of majorArray with:

int (*majorArray)[1000] = calloc(1000, sizeof majorArray);
Nikolai N Fetissov
This being homework, `malloc` may not be allowed.
Zack
+7  A: 

Your program works correctly on my computer (x86-64/Linux) so I suspect you're running into a system-specific limit on the size of the call stack. I don't know how much stack you get on Cygwin, but your array is 4,000,000 bytes (with 32-bit int) - that could easily be too big.

Try moving the declaration of majorArray out of main (put it right after the #includes) -- then it will be a global variable, which comes from a different allocation pool that can be much bigger.

By the way, this comparison is backwards:

if(rowMajor>colMajor)
{
  printf("Row major is faster\n");
}
else
{
   printf("Column major is faster\n");
}

Also, to do a test like this you really ought to repeat the process for many different array sizes and shapes.

Zack
Oh, whoops. Thanks for that catch! ^.^;; ALSO: Moving majorArray out of the main function did the trick, thank you!
Raven Dreamer
+1  A: 

The program is working perfectly when compiled by gcc, & run in Linux, Cygwin may very well be your problem here.

Kedar Soparkar
+3  A: 

I was unable to find any error in your code, so I compiled it and run it and worked as expected.

You have, however, a semantic error in your code:

   start=clock();
   //set it up to perform the test 100 times.
   for(int k = 0; k<10; k++)
   {

Should be:

   //set it up to perform the test 100 times.
   for(int k = 0; k<10; k++)
   {
   start=clock();

Also, the condition at the end should be changed to its inverse:

if(rowMajor<colMajor)

Finally, to avoid the problem of the os-specific stack size others mentioned, you should define your matrix outside main():

#include <stdio.h>
#include <time.h>

int majorArray [1000][1000];

int main(void){
   //first define the array and two doubles to count elapsed seconds.   
   double rowMajor, colMajor;
   rowMajor = colMajor = 0;
Baltasarq
Thank you. I caught the problem with the start clock myself, and have now updated the OP to reflect that.
Raven Dreamer
A: 

If it runs correctly elsewhere, you're most likely trying to grab more stack space than the OS allows. You're allocating 4MB on the stack (1 mill integers), which is way too much for allocating "safely" on the stack. malloc() and free() are your best bets here.

Maister