Thread: Segmentation Fault -_-

  1. #1
    Registered User
    Join Date
    Dec 2011
    Posts
    11

    Segmentation Fault -_-

    Hey guys, I was wondering if you had any idea about this. Basically I'm creating a program to model Diffusion Limited Aggregation and am having segmentation errors due to my array memory allocation. After loads of debugging I've narrowed it down to the while loop that I use for my random walk. This while loop basically runs through the array "grid" checking every element adjacent to the "particle". If the particle becomes adjacent to another particle in the grid, the value of the element in the array changes from 0 to 1, and the whole process begins again for a new particle. The model works fine for an array of dimension 10x10 and for 5 particle. However, when it gets to higher dimensions and more particles, aka the more steps in the while loop, it fails and gives me segmentation error. Here's the source code, any help appreciated.
    Code:
    #include <stdlib.h>
    #include <math.h>
    #include <stdio.h>
    #include <time.h>
    
    double *lAlloc  (int size);
    int     stick(int **grid, int size, int noPars);
    double    seedLoc(int size, int *centrex, int *centrey);
    
    
    int main()
    {
        int size = 10000;
        int **grid, i, l, n;
        grid = (int **)malloc(size * sizeof(int *) );
        for ( i = 0 ; i < size ; ++i ) 
        {
            grid[i] = (int *) malloc( size * sizeof(int *) );
        }
        if(grid == NULL)
        {
            puts("........ dun ........ed up");
        }
        else
        {stick(grid, 100, 5);
        }
        for(l = 0; l<100; l++)
        {
            for (n = 0; n<100; n++) {
                if(grid[l][n] == 1)
                {
                printf("X = %d, Y = %d, VAL = %d\n",l,n, grid[l][n]);
                }
            }
        }
        
    }
    
    
    
    double    seedLoc(int size, int *centrex, int *centrey)
    {
        puts("got here 1");
        *centrex = size/2;
        *centrey = size/2;
    }
    
    int stick(int **grid, int size, int noPars)
    {
        int centrex, centrey, i, j, k, posX, posY;
        int rnd, newX, newY, step;
        srand((unsigned)time(NULL)); // To increase Pseudorandomness by using a dynamic seed.
        
        seedLoc(size, &centrex, &centrey);
        printf("Centrex, Centry: %d %d\n",centrex, centrey);
        for (i=0; i < size; i++) 
        {
            for (j=0; j<size; j++) 
                {
                    grid[i][j] = 0;
                }
        }
        grid[centrex][centrey] = 1;
        printf("Seed Value %d\n", grid[centrex][centrey]);
        
        
        //choosing random particle firing location on edge of grid
    
        if(((rand() % 4)+1) == 1)
        {
            posX = 0;
            posY = rand() % size;
        }
        else if(((rand() % 4)+1) == 2)
        {
            posY = 0;
            posX = rand() % size;
        }
        else if(((rand() % 4)+1) == 3)
        {
            posY = size;
            posX = rand() % size;
        }
        else
        {
            posY = rand() % size;
            posX = size;
        }
        printf("posY %d,posX %d\n", posX, posY);
        
        for (k = 0; k < noPars; k++) 
        {
            printf("k = %d\n", k);
            newX = posX;
            newY = posY;
            int l, n;
            int m = 0;
            
            while (
                   ((grid[newX + 1][newY] || grid[newX - 1][newY] || grid[newX][newY - 1] || grid[newX][newY + 1]) != 1)
                  )
            {
                //printf("newX: %d, newY: %d, rnd = %d, size = %d, Step Number = %d\n", newX, newY, rnd, size, m);
                rnd = rand() % 4 + 1;
    
                step = 1;
                
                if(rnd == 1)
                {
                    if(newX == size)
                    {
                        step = step * (-1);
                    }
                    newX = newX + step;
                }
                
                else if(rnd == 2)
                {
                    newX = newX - 1;
                    newX = abs(newX);
                }
                
                else if(rnd == 3)
                {
                    if(newY == size)
                    {
                        step = step * (-1);
                    }
                    newY = newY + step;
                }
                
                else
                {
                    newY = newY - 1;
                    newY = abs(newY);
                }
                m = m + 1;
            }
            
            grid[newX][newY] = 1;
            printf(",mX = %d, Y = %d, VAl = %d\n", newX, newY, grid[newX][newY]);
            
            
        
        }
    }

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    1) In main() you leave the testing of grid == NULL too late. You need to check grid == NULL before the loop to assign grid[i], and also check that each grid[i] is non-NULL. Any of the malloc() calls can potentially fail.

    2) You are creating grid, in main(), as a 10000 by 10000 array, but telling stick() it is a 100 by 100 array. That means grid[newX][newY] inside stick() do not correspond to grid[newX][newY] inside main() unless newX is zero. There is a reason that, when passing 2D arrays to a function, that you need to specify all but one of the dimensions. By using a pointer, you are hiding dimensions from the compiler ..... and then telling it to use dimensions that differ between caller and callee.

    3) Because of point 2, when you print elements of grid, you are accessing and printing multiple uninitialised elements of grid (in main()). That is undefined behaviour. As you increase the dimensions, you are increasing the number of times your codes exhibits undefined behaviour, and therefore increasing chances of symptoms (for example, a crash). In practice, however, that is more likely to print garbage values than cause a crash. But it is still dangerous practice.

    4) Inside stick(), the values posX and posY are in the range [0, size-1]. The computations of newX and newY and and subtract 1 all over the place from those starting values. So the values of newX and newY are not necessarily in the range [0, size-1] - your code potentially calculates newX and new Y as a negative value, or as size (or more). But you then set grid[newX][newY] to 1. That is undefined behaviour, and a class of undefined behaviour likely to cause a crash: it is tromping some random area of memory.

    Unrelated to your problem, it is really bad style to use l (letter ell) as a variable name. In code, the letter 'l' and the digit '1' look a lot alike. That can introduce some really subtle and difficult-to-find errors in your code.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    Registered User
    Join Date
    Dec 2011
    Posts
    11
    In regards to 2), the only reason I set size = 10,000 was to provide as much memory as possible to the grid array because of all of the segmentation faults I was getting. I just assumed that the faults were due to a lack of memory or something. The weird thing is that it works up to grid = 10. The number of steps in the while loop is very small. But when the grid array increases, i get serious segmentation faults that screw up the whole calculation =/.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    My point is that you should not simulate a multi-dimensional array with one set of dimension, and tell a called function it has different dimensions (unless you know exactly what you are doing, which you clearly don't).
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    You might try adding the three missing return statements.

    Tim S.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > My point is that you should not simulate a multi-dimensional array with one set of dimension,
    > and tell a called function it has different dimensions (unless you know exactly what you are doing, which you clearly don't).
    But the "array" isn't a 2D array (as in int arr[100][100]), it is an int**
    So long as size is within the bounds of each level of indirection, then accessing arr[row] (the first level) would be just fine, if 100 were allocated and you only used the first 10.
    The same goes for each arr[row][col].

    Besides, if it really was int arr[100][100], and the function were declared int stick(int grid[10][10], int size), then the compiler would complain when called with arr as the parameter. Declaring int stick(int grid[100][100], int size) and calling it with any size <100 would be fine as well. There is plenty of simple code for handling matrices upto a certain size which just uses the top-left corner of some large statically sized array.

    The real problem as I could see it is all those +/-1 in
    grid[newX + 1][newY] || grid[newX - 1][newY] || grid[newX][newY - 1]
    accessing OUTSIDE the allocated memory when the XY values are 0 or size-1
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Salem View Post
    > My point is that you should not simulate a multi-dimensional array with one set of dimension,
    > and tell a called function it has different dimensions (unless you know exactly what you are doing, which you clearly don't).
    But the "array" isn't a 2D array (as in int arr[100][100]), it is an int**
    True. But using an int ** to simulate a 1000x1000 array in main and telling the called function the simulated array is 100x100 is potentially problematical. Not always, true, but that's the reason for my comment about knowing what is going on.

    Quote Originally Posted by Salem View Post
    The real problem as I could see it is all those +/-1 in
    grid[newX + 1][newY] || grid[newX - 1][newY] || grid[newX][newY - 1]
    accessing OUTSIDE the allocated memory when the XY values are 0 or size-1
    Which was the fourth point in my previous post.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  8. #8
    Registered User
    Join Date
    Dec 2011
    Posts
    11
    I'm still getting the error despite changing my loop to ensure that XY values are never 0 or size. I'm not accessing any memory outside the allocated memory, so I'm quite baffled . Also I changed it so that newX and newY never initialise as 0 or size-1.

    Code:
            while (
                   ((grid[newX + 1][newY] || grid[newX - 1][newY] || grid[newX][newY - 1] || grid[newX][newY + 1]) != 1)
                  )
            {
                //printf("newX: %d, newY: %d, rnd = %d, size = %d, Step Number = %d\n", newX, newY, rnd, size, m);
                rnd = rand() % 4 + 1;
    
                step = 1;
                
                if(rnd == 1)
                {
                    if(newX == size - 1)
                    {
                        step = step * (-1);
                    }
                    newX = newX + step;
                }
                
                else if(rnd == 2)
                {
                    if(newY == 1)
                    {    
                        step = step * (-1);
                    }
                    newX = newX - (step);
                }
                
                else if(rnd == 3)
                {
                    if(newY == size - 1)
                    {
                        step = step * (-1);
                    }
                    newY = newY + step;
                }
                
                else
                {
                    if(newY == 1)
                    {    
                        step = step * (-1);
                    }
                    newY = newY - (step);
                    
                }
    Last edited by Bro; 12-26-2011 at 03:06 PM.

  9. #9
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Your while statement condition is strange. You might mean
    Code:
    while (grid[newX + 1][newY] != -1 && grid[newX - 1][newY] != -1 && grid[newX][newY - 1] != -1 && grid[newX][newY + 1] != 1)
    (or possibly you want || instead of &&). Also the line
    Code:
    if(((rand() % 4)+1) == 1)
    and the following lines are probably not what you want either. Assign the random value to a variable just before the if and use that in your if conditions. I would've posted more code, but posting code doesn't seem to work for me (it ends up all on one line).

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Are you sure?

    Code:
            posX = 0;
    ...
            newX = posX;
    ...
                   ((grid[newX + 1][newY] || grid[newX - 1][newY] || grid[newX][newY - 1] || grid[newX][newY + 1]) != 1)
    What array element are you accessing here?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Dec 2011
    Posts
    11
    Code:
    #include <stdlib.h>
    #include <math.h>
    #include <stdio.h>
    #include <time.h>
    
    int     stick(int **grid, int size, int noPars);
    double    seedLoc(int size, int *centrex, int *centrey);
    
    
    int main()
    {
        int size = 10;
        int **grid, i, l, n;
        grid = (int **)malloc(size * sizeof(int *) );
        if(grid == NULL)
        {
            puts("........ dun ........ed up");
        }
        for ( i = 0 ; i < size ; ++i ) 
        {
            grid[i] = (int *) malloc( size * sizeof(int *) );
        }
        if(grid == NULL)
        {
            puts("........ dun ........ed up");
        }
        else
        {stick(grid, 10, 3);
        }
        for(l = 0; l<100; l++)
        {
            for (n = 0; n<100; n++) {
                if(grid[l][n] == 1)
                {
                printf("X = %d, Y = %d, VAL = %d\n",l,n, grid[l][n]);
                }
            }
        }
        
    }
    
    
    double    seedLoc(int size, int *centrex, int *centrey)
    {
        puts("got here 1");
        *centrex = size/2;
        *centrey = size/2;
    }
    
    int stick(int **grid, int size, int noPars)
    {
        int centrex, centrey, i, j, k, posX, posY;
        int rnd, newX, newY, step;
        srand((unsigned)time(NULL)); // To increase Pseudorandomness by using a dynamic seed.
        
        seedLoc(size, &centrex, &centrey);
        printf("Centrex, Centry: %d %d\n",centrex, centrey);
        for (i=0; i < size; i++) 
        {
            for (j=0; j<size; j++) 
                {
                    grid[i][j] = 0;
                }
        }
        grid[centrex][centrey] = 1;
        printf("Seed Value %d\n", grid[centrex][centrey]);
        
        
        //choosing random particle firing location on edge of grid
    
        if(((rand() % 4)+1) == 1)
        {
            posX = 1;
            posY = rand() % size;
        }
        else if(((rand() % 4)+1) == 2)
        {
            posY = 1;
            posX = rand() % size;
        }
        else if(((rand() % 4)+1) == 3)
        {
            posY = size - 1;
            posX = rand() % size;
        }
        else
        {
            posY = rand() % size;
            posX = size - 1;
        }
        printf("posY %d,posX %d\n", posX, posY);
        
        for (k = 0; k < noPars; k++) 
        {
            printf("k = %d\n", k);
            newX = posX;
            newY = posY;
            int l, n;
            int m = 0;
            
            while (
                   ((grid[newX + 1][newY] || grid[newX - 1][newY] || grid[newX][newY - 1] || grid[newX][newY + 1]) != 1)
                  )
            {
                printf("newX: %d, newY: %d, rnd = %d, size = %d, Step Number = %d\n", newX, newY, rnd, size, m);
                rnd = rand() % 4 + 1;
    
                step = 1;
                
                if(rnd == 1)
                {
                    if(newX == size - 1)
                    {
                        step = step * (-1);
                    }
                    newX = newX + step;
                }
                
                else if(rnd == 2)
                {
                    if(newY == 1)
                    {    
                        step = step * (-1);
                    }
                    newX = newX - (step);
                }
                
                else if(rnd == 3)
                {
                    if(newY == size - 1)
                    {
                        step = step * (-1);
                    }
                    newY = newY + step;
                }
                
                else
                {
                    if(newY == 1)
                    {    
                        step = step * (-1);
                    }
                    newY = newY - (step);
                    
                }
                m = m + 1;
            }
            
            grid[newX][newY] = 1;
            printf(",mX = %d, Y = %d, VAl = %d\n", newX, newY, grid[newX][newY]);
            
            
        
        }
    }

    Sorry I didn't post my full code. Here's my updated one, as you can see, posX and posY are never equal to 0 nor size.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Code:
        {stick(grid, 10, 3);
        }
        for(l = 0; l<100; l++)
        {
            for (n = 0; n<100; n++) {
    You've got a constant called size - USE IT.

    > grid[i] = (int *) malloc( size * sizeof(int *) );
    This should be sizeof(int)
    Also, the cast of malloc is unnecessary in C - see the FAQ.

    You should also check if ( grid[i] == NULL ) inside the loop, not another (pointless) if ( grid == NULL ) outside the loop.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Registered User
    Join Date
    Dec 2011
    Posts
    11
    I tried all those things, I still get this same error. The array is not null within the loop.

  14. #14
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    You need something like this for your while loop (ignore my last post; I didn't understand what you were up to, although the second point there is still valid).
    Code:
    while (newX < size-1 && grid[newX+1][newY] || newX > 0 && grid[newX-1][newY] || newY > 0 && grid[newX][newY-1] || newY < size-1 && grid[newX][newY+1])
    Do you really only want to test horizontally and vertically or do you want to test diagonally as well?

  15. #15
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Your computations of newX and newY are still going out of the range [0, size-1], despite your claim you have fixed that. And you are still adding and subtracting one in order to access some elements.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. segmentation fault!!
    By Necromancer in forum C++ Programming
    Replies: 3
    Last Post: 02-26-2008, 08:03 AM
  2. Segmentation fault
    By (Slith++) in forum C++ Programming
    Replies: 4
    Last Post: 05-06-2007, 03:47 AM
  3. segmentation fault??
    By snappleapple in forum C Programming
    Replies: 9
    Last Post: 04-27-2007, 11:56 PM
  4. Segmentation Fault
    By warfang in forum C++ Programming
    Replies: 9
    Last Post: 04-23-2007, 01:42 AM
  5. segmentation fault and memory fault
    By Unregistered in forum C Programming
    Replies: 12
    Last Post: 04-02-2002, 11:09 PM