Hi all, I have 2 quick questions, I have a pure C text game, very small, just 1 test area created so far. But already 50% of the time I get a heap corruption crash (Visual studio IDE). I see about 4 functions in the call stack, with the last function shown below. I appreciate this probably won't be enough for anyway to determine why it got corrupted, but I just want to rule out any glaringly obvious errors with the below malloc wrapper, and typical usage.
typedefstruct option
{
char *name;
void(*func_ptr)(void);
int active;
} option_t;
but display_inventory takes a struct param. Is this the best way to get a generic function pointer and will I have to live with the warning? The basic design idea is to have an area, which has an array of option_t pointers, the player enters a number corresponding to one of the options, and the appropriate 'action' is executed. E.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
void parse_cmd(area_t *area, int cmd)
{
if (cmd == ESCAPE_CMD)
exit(0);
if (cmd < 1 || cmd > area->numOfOptions)
{
m_error("INVALID COMMAND");
return;
}
int option = cmd - 1;
int isLookAround = strcmp(area->options[option]->name, "Look Around");
if (isLookAround == 0)
area_display_description(area);
else
area->options[option]->func_ptr();
}
Is this the best way to get a generic function pointer
Yes, but you must convert the function pointer into the correct type when doing anything with it. Just insert a type cast.
Finally, a question for you:
Why choose ((void*)0) when NULL would be suitable?
Is NULL defined as a literal zero on your system? #define NULL 0
This is a problematic definition in C++, but is it problematic for C programs? If yes, how?
Line 15: Why do you have sizeof() there? strlen() returns a value of type size_t which is either 4 or 8 bytes. You are effectively doing the following:
Thanks guys! That is indeed it, I wasn't allocating enough space for the names by using sizeof incorrectly. Doesn't appear to be crashing anymore... :)
mbozzi in answer to your query, no reason not to use NULL, I was just using it there from an example
in terms of casting the function pointer, did you mean like this?
&display_inventory already has type void (*)(struct inventory *) so converting it into that type doesn't do anything.
I meant inventory->func_ptr = (void (*)(void)) &display_inventory;
And then when you call it it needs to be converted back into the original type
(((void (*)(struct inventory *))(inventory->func_ptr))(&my_inventory);
To accommodate multiple arguments, put each argument in a structure and pass a pointer to the structure. (My C programming skills are rusty, but hopefully this gets the point across any way.)
I don't know whether the void* alternative is materially better than what you described, but I would have used a void* out of habit.