Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are char ** objects saved? [closed]

Today, I asked me, how char ** objects are saved in memory or in binary files. I tested that with the following code snippet:

char **array  = (char *)malloc(3 * sizeof(char *));

array[0] = "Foo";         // Length: 3
array[1] = "Long string"; // Length: 11
array[2] = "Bar";         // Length: 3   => Full length: 17

int length = 17;

I write this array to a file:

FILE *file = fopen(...);
fwrite(array, length, 1, file);
fclose(file);

The great thing is that when I read again this array from file with the following code, the string lengths are read successfully without saving more than 17 bytes.

FILE *file   = fopen(...);
int   length = 17;

char **array = (char *)malloc(length);

int index        = 0;
int parsedLength = 0;
while (parsedLength < length)
{
    char *string       = array[index];
    int   stringLength = strlen(string);

    printf("%i: \"%s\" (%i)\n", index, string, stringLength);

    parsedLength += stringLength;
    ++index;
}

I get an output that equals:

0: "Foo" (3)
1: "Long string" (11)
2: "Bar" (3)

How does the compiler know, how long each string in the array is?

like image 925
Paul Warkentin Avatar asked Feb 23 '26 12:02

Paul Warkentin


2 Answers

Pointers are saved to a file like numbers (or better addresses) so the fact that your code works is an illusion created by the fact that you are probably saving and loading them inside the same program in the same run (so since these string are literals, their address is mostly fixed in data segment).

What you are doing is completely wrong because array's layout in memory is the following (I'm assuming 4 bytes pointers):

XXXXXXXX YYYYYYYY ZZZZZZZZ ( = 12 bytes)
   ^        ^        ^
   |        |       pointer to "Bar"
   |      pointer to "Long String"
 pointer to "Foo"

but you are saving 17 bytes onto the file, 12 of which are just memory addresses.

To correctly save strings in the file you will certainly need to store the whole data contained and its length. Something like:

for (int i = 0; i < ARRAY_LENGTH; ++i) {
  char *string = array[i];
  unsigned int length = strlen(string);
  fwrite(&length, sizeof(unsigned int), 1, out);
  fwrite(string, sizeof(char), length, out);
}

for (int i = 0; i < ARRAY_LENGTH; ++i {
  unsigned int length;
  fread(&length, sizeof(unsigned int), 1, in);
  array[i] = calloc(sizeof(char), length);
  fread(array[i], sizeof(char), length, in);
}
like image 132
Jack Avatar answered Feb 26 '26 00:02

Jack


In don't think your program works. Try to write a new program which read your file, or try to open the binary file with an hex editor. The strings aren't present in it. char ** array is an array of pointer not an array of char and its size is 3*4 = 12 on 32 bits common environment.

like image 24
Aubin Avatar answered Feb 26 '26 00:02

Aubin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!