views:

52

answers:

6

The following code causes a SIGSEGV, but only while debugging.

#include <stdio.h>
#include <stdlib.h>

typedef struct enemy_desc
{
int type;
int x;
int y;
}enemy;

int main()
{
    enemy **enemies;
    enemies=(enemy **)malloc(sizeof(enemy *)*16);

    enemies[0]->type=23;

    printf("%i",enemies[0]->type);
    return 0;
}
+2  A: 

You need to create the struct that the pointers point to. The reason why it only gives a SEGV while debugging will be that there's some initialisation done during debugging to cause this sort of thing to segfault; whatever random data's in enemies[0] when you're not debugging is getting dereferenced and is just happening not to cause a segfault.

Your code probably wants to read like this:

    int main()
{
    enemy *enemies;
    enemies=(enemy *)malloc(sizeof(enemy)*16);

    enemies[0].type=23;

    printf("%i",enemies[0].type);
    return 0;
}
David Knell
A: 

On my system (x86, Debian GNU/Linux), the code always segfaults.

Crash backtrace:

signal SIGSEGV, Segmentation fault.
0x08048413 in main () at en.c:16
16      enemies[0]->type=23;
(gdb) 

The assignment cited (enemies[0]->type=23;) is the problem. You only allocate memory for the array enemies, which is an array of pointers. You then access the structure that enemies[0] is supposed to point to, but you have not allocated memory for the structure, and enemies[0] is an uninitialized pointer, hence the segfault.

In cases like this, a debugger is your friend :-).

sleske
+4  A: 

You are only creating space for 16 pointers to enemy, but are not creating the actual enemy objects that you're attempting to use.

Here is an example where I create an enemy object to the first pointer in the array.

#include <iostream>

typedef struct enemy_desc
{
int type;
int x;
int y;
}enemy;

using namespace std;
int main(int argc, char **argv)
{
    enemy **enemies;
    enemies=(enemy **)malloc(sizeof(enemy *)*16);
    memset(enemies, 0, sizeof(enemy*)*16);

    enemies[0] = (enemy *) malloc(sizeof(enemy));
    memset(enemies[0], 0, sizeof(enemy));

    enemies[0]->type=23;
    printf("type: %i  x: %i  y: %i\n\n",enemies[0]->type, enemies[0]->x, enemies[0]->y);

    enemies[0]->x = 10;
    enemies[0]->y = 25;
    enemies[0]->type= 7;
    printf("type: %i  x: %i  y: %i\n\n",enemies[0]->type, enemies[0]->x, enemies[0]->y);

    free(enemies[0]);
    free(enemies);
    return 0;
}
RC
+1  A: 

Looks like you want to allocate an array of pointer to struct, but you're trying to access the struct without allocating space for them. You should do:

enemy **enemies;
enemies=(enemy **)malloc(sizeof(enemy *)*16);
for(i=0;i<16;i++) // allocate space for the structs
 enemies[i] = (enemy *)malloc(sizeof(enemy))
enemies[0]->type=23; // now access type field of the first struct obj in array.
codaddict
Thanks, this is exactly what I was trying to do.
Ryan S
+3  A: 

You have allocated memory for 16 enemy * pointers, but you have not allocated room for the 16 enemy structs themselves. There are two ways to fix this. One is to add a loop that allocates each of the 16 enemy structs one by one:

int main()
{
    enemy **enemies;
    int i;

    enemies = (enemy **) malloc(sizeof(enemy *) * 16);

    for (i = 0; i < 16; ++i) {
        enemies[i] = (enemy *) malloc(sizeof(enemy));
    }

    enemies[0]->type = 23;

    printf("%i",enemies[0]->type);
    return 0;
}

The other is to remove one level of indirection. If you declare enemy *enemies then you can allocate the 16 structs at once and forgo a loop. If there's no need for the double indirection this would be my preferred solution:

int main()
{
    enemy *enemies;
    enemies = (enemy *) malloc(sizeof(enemy) * 16);

    enemies[0].type=23;

    printf("%i",enemies[0].type);
    return 0;
}

Notice that the -> operator switches to ..

John Kugelman
+2  A: 

Well it should crash right away... because you initialize the array of (array of pointers). And then you DEREFERENCE the first item (enemies[0]) which should give you any random pointer. You try to access that random memory area to write in the value 23.

It should be along the lines of this:

enemies = (enemy **)malloc(sizeof(enemy *) * 16);
for (int i = 0; i < 16; i++) {
  enemies[i] = (enemy *)malloc(sizof(enemy));
}

... before you access it.

DarkDust