keeping track of how much memory malloc has allocated

c, char, malloc

Solution

You will want to allocate the space for both the length and the string in the same block of memory. This may be what you intended with your struct, but you have reserved space for only a pointer to the string.

There must be space allocated to contain the characters of the string.

For example:

typedef struct
{
    int num_chars;
    char string[];
} my_string_t;

my_string_t * alloc_my_string(char *src)
{
    my_string_t * p = NULL;
    int N_chars = strlen(src) + 1;

    p = malloc( N_chars + sizeof(my_string_t));
    if (p)
    {
         p->num_chars = N_chars;
         strcpy(p->string, src);
    }
    return p;
}

In my example, to access the pointer to your string, you address the `string` member of the `my_string_t`:

my_string_t * p = alloc_my_string("hello free store.");
printf("String of %d bytes is '%s'\n", p->num_chars, p->string);

Be careful to realize that you are obtaining the pointer for the string as a consequence of allocating space to store the characters. The resource you are allocating is the storage for the characters, the pointer obtained is a reference to the allocated storage.

In my example, the memory allocated is laid out sequentially as follows:

+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| 00 | 00 | 00 | 11 | 'h'| 'e'| 'l'| 'l'| 'o'| 20 | 'f'| 'r'| 'e'| 'e'| 20 | 's'| 't'| 'o'| 'r'| 'e'| '.'| 00 |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
^^                   ^
||                   |
p|                   |
 p->num_chars        p->string

Notice that the value of `p->string` is not stored in the allocated memory, it is four bytes from the beginning of the allocated memory, immediately subsequent to the (presumed 32-bit, four-byte) integer.

Your compiler may require that you declare the flexible C array as:

typedef struct
{
    int num_chars;
    char string[0];
} my_string_t;

but the version lacking the zero is supposedly C99-compliant.

You can accomplish the equivalent thing with no array member as follows:

typedef struct
{
    int num_chars;
} mystr2;

char * str_of_mystr2(mystr2 * ms)
{
    return (char *)(ms + 1);
}

mystr2 * alloc_mystr2(char *src)
{
    mystr2* p = NULL;
    size_t N_chars = strlen(src) + 1;

    if (N_chars num_chars = (int)N_chars;
         strcpy(str_of_mystr2(p), src);
    }
    return p;
} 

printf("String of %d bytes is '%s'\n", p->num_chars, str_of_mystr2 (p));

In this second example, the value equivalent to `p->string` is calculated by `str_of_mystr2()`. It will have approximately the same value as the first example, depending on how the end of structs are packed by your compiler settings.

While some would suggest tracking the length in a `size_t` I would look up some old Dr. Dobb's article on why I disagree. Supporting values greater than INT_MAX is of doubtful value to your program's correctness. By using an int, you can write `assert(p->num_chars >= 0);` and have that test something. With an unsigned, you would write the equivalent test something like `assert(p->num_chars < UINT_MAX / 2);` As long as you write code which contains checks on run-time data, using a signed type can be useful.

On the other hand, if you are writing a library which handles strings in excess of UINT_MAX / 2 characters, I salute you.

Problem

After a quick scan of related questions on SO, I have deduced that there's no function that would check the amount of memory that malloc has allocated to a pointer. I'm trying to replicate some of std::string basic functionality (mainly dynamic size) using simple char*'s in C and don't want to call realloc all the time. I guess I'll need to keep track of how much memory has been allocated. In order to do that, I'm considering creating a typedef that will contain the string itself and an integer with the amount of memory currently allocated, something like this: ``` typedef struct { char * str; int mem; } my_string_t; ``` Is that an optimal solution, or perhaps you can suggest something that will bear better results? Thanks in advance for your help.

Original source