1
output_s = (char**)malloc(sizeof(char*));
output_s[0] = (char*)malloc(sizeof(char));
output_s[0] = NULL;

So what I'm trying to create is a char array that would normally be a char array of char* strings, but for this specific input case I want to make an array that only contains a NULL entry, and for some reason when I create the entry I can free my array, but cannot free the entry that was set to null and 1 byte is leaked.

  free(result[0]);
  free(result);

That is later called to free the memory, with result being the returned output_s variable from above

==18402== HEAP SUMMARY:
==18402==     in use at exit: 1 bytes in 1 blocks
==18402==   total heap usage: 3 allocs, 2 frees, 1,033 bytes allocated
==18402== 
==18402== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==18402==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-    amd64-linux.so)
==18402==    by 0x4007D1: camel_caser (camelCaser.c:33)
==18402==    by 0x400CE4: test_camelCaser (camelCaser_tests.c:30)
==18402==    by 0x400D47: main (camelCaser_main.c:13)
==18402== 
==18402== LEAK SUMMARY:
==18402==    definitely lost: 1 bytes in 1 blocks
==18402==    indirectly lost: 0 bytes in 0 blocks
==18402==      possibly lost: 0 bytes in 0 blocks
==18402==    still reachable: 0 bytes in 0 blocks
==18402==         suppressed: 0 bytes in 0 blocks

camelCaser.c:33 is the line that mallocs the

output_s[0] = (char*)malloc(sizeof(char));
2
  • How is output_s defined? Commented Jan 28, 2018 at 8:37
  • 3
    Your question can be summarized as int a = 5; a = 14; "why isn't a equal to 5 anymore?" Commented Jan 28, 2018 at 8:38

3 Answers 3

5
output_s[0] = (char*)malloc(sizeof(char));

This allocates memory and stores a pointer to it in output_s[0].

output_s[0] = NULL;

This overwrites the previous pointer with NULL, and thus leaks the memory the previous pointer pointed to, making valgrind report it.

If what you want is the new string to be empty (aka "null string"), then:

output_s[0] = malloc(sizeof(char));
output_s[0][0] = '\0';

But the new string only has space for one character, which suggests this isn't what you want. If you want to allocate memory for a string of N characters, then allocate it with:

output_s[0] = malloc(sizeof(char) * N);
output_s[0][0] = '\0';

Since sizeof(char) is always 1, you can just do this instead:

output_s[0] = malloc(N);
output_s[0][0] = '\0';

Note that this only applies when allocating char arrays. For allocating arrays of other types, you still need sizeof(type) * N.

If you want the whole char** array to be NULL-terminated, then just set the last element to NULL. You don't need to allocate anything extra, since the memory for all the char* elements has already been allocated:

output_s[index] = NULL;

However, if that particular element contains an allocated string, you need to free it first:

free(output_s[index]);
output_s[index] = NULL;

As a side note, I recommend getting rid of the bad habit of casting the return value of malloc(). It's not needed and it can hide errors under certain circumstances. Meaning, use:

output_s[0] = malloc(N);

instead of:

output_s[0] = (char*)malloc(N);
Sign up to request clarification or add additional context in comments.

6 Comments

So say that I needed to make the char** array null terminated, if I allocated it with output_s = (char**)malloc((sizeof(char*) * totalSentences) + 1); then took output_s[totalSentences] = NULL; this would leak memory as well, could I do output_s = '\0' to make it null?
@user3645925 Updated answer. If you want the char** array to be NULL-terminated, just set the last element to NULL without allocating a string there.
Nitpicking: "when allocating strings" you do not do this. You allocate char-arrays, which only then become "strings" the moment at least one of those elements is being set to '\0'.
So if it was a 1 size array of char** and I want it to just contain a null element I don't need the second malloc i can just right off the bat say output_s[0] = NULL without allocating output_s[0] any memory?
@user3645925 Yes. char** output_s = malloc(sizeof(char*) * 1); allocates memory for 1 char* element. You then set that element to NULL with output_s[0] = NULL;
|
0

You cannot free NULL, even if it is stored in a variable which previously contained a non-NULL pointer.
And that non-NULL pointer got lost already sooner, when you wrote the NULL into the same variable.
The malloced memory that non-NULL pointer was pointing to is lost, leaked.

Comments

-1

With free(x), you are asking to deallocate the memory block which resides at address x.

If you set x to 0, then you are asking to deallocate the memory block which resides at address 0.

7 Comments

"... you are asking to deallocate the memory block which resides at address 0." which does nothing, the request silently ignored by the C library.
@alk: I think it is possibly platform-dependent (i.e., not imposed by the language standard).
The behaviour I describe is defined by the C Standard. (7.22.3.3: "... If ptr is a null pointer, no action occurs. ..."
@M.M: Oh well, fair enough, still the OP uses NULL not 0. Also when passing 0 to free() it implicitly gets converted to a null-pointer (6.3.2.3/3).
@alk: Yes, sure, NULL is not necessarily 0 on a given platform, so I should have technically written "at address NULL". Of course, if I did that, then the dude who asked the question would most likely not understand what I meant. And since NULL is practically 0 on every platform out there, I thought that phrasing it as "address 0" would make it easier for him or her to understand.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.