PDA

View Full Version : weird behavior w/ compiler?




wala
Jul 7, 2006, 06:17 PM
Has anyone ever encountered this before in C:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
char **strings;
int i;
strings = (char **) malloc(65);
strings[0] = (char *) malloc(strlen("string") + 1);
strcpy(strings[0], "string");
for (i = 1; i < 65; i++)
strings[i] = NULL;
printf("%s\n", strings[0]);
free(strings[0]);
free(strings);
return 0;
}

When I run the above code, a blank line is printed! Is something wrong?

EDIT: I probably shouldn't be blaming this on the compiler (Apple's gcc). It's probably just my poor coding skills. Still, what is happening?



robbieduncan
Jul 7, 2006, 06:30 PM
If you take out the for loop you get the expected behaviour.

So we ask ourselves why?

Well what have we done? We've allocated an array of 65 elements each of which is big enough to hold a pointer to a character array. Then we malloc some more space for out string at store the result into the first element of our array. And all is good.

Then we string copy "string" into memory starting with the first element of our array. Note the first element, not the memory pointed to by the first element.

The same for the print.

OK, more thought, I'm not totally convinced by more own explanation. All I know is removing the loop makes it work...

wala
Jul 7, 2006, 06:40 PM
When strings[21] and only strings[21] is set to NULL, the output is just "stri".
There is no output when only strings[20] is set to NULL.

robbieduncan
Jul 7, 2006, 06:52 PM
OK. It's really simple.

malloc(65) creates a 65 byte array of memory. A char* pointer is, of course, 32 bits or 4 bytes. So you are totally messing with the string when you start writing NULL at strings[1].

If you change malloc(65) to malloc(65*sizeof(char*)) then it's good.

wala
Jul 7, 2006, 06:57 PM
Thanks. I feel kinda dumb.
Where can I find OS X sizeof() tables for future reference?

iSee
Jul 7, 2006, 07:31 PM
Thanks. I feel kinda dumb.
Where can I find OS X sizeof() tables for future reference?

You don't need tables because the compiler knows. You just use sizeof(sometype). So, to allocate 65 values of type long, you would use:

mylongs = (long *) malloc(65 * sizeof(long));

or 22 floats:

myfloats = (float *) malloc(22 * sizeof(float));

or 17 char*'s:

strings = (char**) malloc(17 * sizeof(char*));

It works for any type, including structs.

wala
Jul 7, 2006, 08:40 PM
I know that, but I was wondering if they are listed anywhere.

robbieduncan
Jul 8, 2006, 02:59 AM
I know that, but I was wondering if they are listed anywhere.

They are decided at compile time. For example if you were to compile in 64bit mode (which you should be able to do for a pure C command line executable I think) pointers would be 64bits instead of 32bits.

You could write a program to print out the sizeof all the basic types...