Array of pointers to struct, only SIGSEGVs while debugging
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;
}
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;
}
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 .
.
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;
}
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.
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.
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 :-).
精彩评论