-1

I'm trying to write Conway's game of life in C. This is what I have so far. I'm using pointers to refer to the arrays, which has never caused me problems before, but the function place_cell is causing a segfault.

Here's what I've tried so far: - I tried making the grid with constants, 100 x 100, and 10 x 10. Modifying values inside of those constant grids still gives me a segfault. - I tried using constants for place_cell, still got a segfault.

int** make_grid(int x, int y) {
    int** is = (int**)malloc(sizeof(int*) * y);
    if(! is) {
        fprintf(stderr, "make_grid: malloc failed");
        exit(1);
    }
    int j;
    for(j = 0; j < y; j++) {
        is[j] = (int*)malloc(sizeof(int) * x);
        if(!is[j]) {
            fprintf(stderr, "make_grid: malloc failed");
            exit(1);
        }
    }
    return is;
}

/* takes two integers and places a cell at those coords */
void place_cell(int** is, int sidex, int sidey, int x, int y) {
    if(x >= sidex || y >= sidey) {
        fprintf(stderr, "place_cell: out of grid range\n");
        exit(1);
    }
    is[y][x] = 1;
}

int check_surroundings(int** is, int sidex,
                       int sidey, int x, int y) {
    int y_less = y - 1;
    if(y == 0) {
        y_less = sidey - 1;
    }
    int y_more = y + 1;
    if(y == sidey - 1) {
        y_more = 0;
    }
    int x_less = x - 1;
    if(x == 0) {
        x_less = sidex - 1;
    }
    int x_more = x + 1;
    if(x == sidex - 1) {
        x_more = 0;
    }
    int p = is[y_less][x_less] +
        is[y_less][x] +
        is[y_less][x_more] +
        is[y][x_less] +
        is[y][x_more] +
        is[y_more][x_less] +
        is[y_more][x_less] +
        is[y_more][x_more];
    return p;
}

void change_condition(int** is,
                      int sidex, int sidey, int x, int y) {
    int* state = &is[y][x];
    int surr = check_surroundings(is, sidex, sidey, x, y);
    if(surr > 3) {
        *state = 0;
    } else if(surr == 3 || surr == 2) {
        *state = 1;
    } else {
        *state = 0;
    }
}

void print_grid(int** is, int sidex, int sidey) {
    int i, j;
    for(i = 0; i < sidey; i++) {
        for(j = 0; j < sidex; j++) {
            if(is[i][j] == 1) {
                printf("*");
            } else {
                printf(" ");
            }
        }
        printf("\n");
    }
}

void new_generation(int** is, int sidex, int sidey) {
    int i, j;
    for(i = 0; i < sidey; i++) {
        for(j = 0; j < sidex; j++) {
            change_condition(is, sidex, sidey, j, i);
        }
    }
}

void play(int** is, int sidex, int sidey) {
    int i = 0;
    while(i < 100) {
        new_generation(is, sidex, sidey);
        print_grid(is, sidex, sidey);
        i++;
    }
}

here's my main:

int main(int argc, char* argv[]) {

    int sidex = atoi(argv[0]);
    int sidey = atoi(argv[1]);
    int** is = make_grid(10, 10);
    int i;
    for(i = 2; i < argc; i += 2) {
        place_cell(is, sidex, sidey,
                   atoi(argv[i]), atoi(argv[i + 1]));
    }

    return 0;
}

edit:

int** make_grid(int x, int y) {
    int (*is)[x] = (int*)malloc(sizeof(int) * y * x);
    if(! is) {
        fprintf(stderr, "make_grid: malloc failed");
        exit(1);
    }
    int j;
    for(j = 0; j < y; j++) {
        is[j] = (int*)malloc(sizeof(int) * x);
        if(!is[j]) {
            fprintf(stderr, "make_grid: malloc failed");
            exit(1);
        }
    }
    return is;
}

This isn't right at all but I can't put my finger on why. Can someone explain to me what to change like I'm five? (a five year-old who knows C, I guess)

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
A. Hunter
  • 21
  • 5
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/143359/discussion-on-question-by-a-hunter-conways-game-of-life-segfault-11). – Bhargav Rao May 04 '17 at 06:59

2 Answers2

0

I just copied your entire code and tried to run the program. The memory access violation (at least for me) is in this line:

int sidex = atoi(argv[0]);
int sidey = atoi(argv[1]);    <-- memory access violation

The reason is (in my case at least) that I just ran the program with no arguments.

Now, even if I did provide the arguments on the command line the indexing is still off. The first argument argv[0] is the name of the executable, not the first argument after the name.

So, a few things to note for your code:

  1. It is not guaranteed that there will be arguments. You should always check the argc to make sure you can index into argv
  2. Those arguments are not guaranteed to be integer numbers either - you better check for that too, before you use them as your dimensions

Of course with the indexing shift you should adjust for your "array reading" code accordingly as well. But once you fix the indexing this should be an easy one for you

YePhIcK
  • 5,816
  • 2
  • 27
  • 52
  • I think there's more than one, because when I took that code out entirely and just passed constants I still had problems – A. Hunter May 03 '17 at 21:24
  • 1
    Debugger is your friend then ;-) – YePhIcK May 03 '17 at 21:25
  • May I suggest you use a graphical IDE? Like the free MS Visual Studio (on Windows). A debugger is integrated in there and is quite easy to use. – YePhIcK May 03 '17 at 22:16
  • @YePhIcK: An IDE is not required for debugging. gdb works fine on the console. – too honest for this site May 03 '17 at 23:05
  • 1
    @A.Hunter: YOu have to compile with debug support enabled. No offence, but you really should do some tutorials on the fundamentals before you start such a project. That should have been part of your class actually beforehand. – too honest for this site May 03 '17 at 23:08
  • @Olaf of course and IDE is not *required*. Was just trying to suggest something "easy" for the situation – YePhIcK May 03 '17 at 23:11
  • @YePhIcK A full-gorwn IDE is definitively not "something easy" to start with. A first approach might be `printf` debugging. Anyway, that whole question is messed up too much anyway. I just suggested OP to delete it and first process all the comments. Quite a lot for a beginner to comprehend already. – too honest for this site May 03 '17 at 23:14
  • @YePhIcK: Note that if he can use VLAs, he is not using MSVC. And as this is not standard compliant and does not support VLAs, I strongly discourage using it anyway. A modern compiler like gcc or clang would be free, too and compliant. – too honest for this site May 03 '17 at 23:16
  • A learning curve for a graphical IDE is much smoother than for a command-line environment, IMHO. But I agree with the suggestion to OP to get some basics covered before proceeding further. – YePhIcK May 03 '17 at 23:17
  • I'm compiling with clang and I put -g in the Makefile. I don't understand why you're all being condescending, I know how to use a debugger but in this particular situation it isn't giving me useful information and if you all think that I'm being too dense you can leave the thread. – A. Hunter May 04 '17 at 21:52
-1

You are not declaring a two-dimensional array with that syntax, so the memory is not aligned the way you think, thus a segmentation fault. Declaring a pointer int** does not make it a 2-D array. (Surely you don't think int *** would get you a data cube ?).

Heap allocate a 2D array (not array of pointers)

One of the comments above gives the other problem, the zero parameter to a C program argv[0] is the name of the program, not the first parameter on the command line, that is argv[1].

Community
  • 1
  • 1
Jeff D.
  • 328
  • 1
  • 7