-1

I wrote the following code:

[all the required initialization]

printf("longueur de mid: %d\n",mid);

L = (char*) malloc((mid)*sizeof(char));

printf("longueur de L: %d\n",strlen(L));

[data treatment and free()]

And with the printf I got this result:

longueur de mid: 2
longueur de L: 3

Why do the outputs differ?

White
  • 71
  • 1
  • 13
  • 3
    You want to read on what C-"strings" really are, as there is no data type "string" in C. – alk Oct 28 '15 at 18:53
  • 1
    If you initialize with `null-characters` (zero), you will see the difference. i.e. `L = calloc(mid, sizeof(char));` and `R = calloc((n - mid), sizeof(char));` (**note:** for storage of a string of `mid`, you must allocate `mid + 1` to provide room for the null-terminating character) – David C. Rankin Oct 28 '15 at 19:11
  • 2
    You've allocated memory but you've put nothing into it. So its contents are random, and might have any string length. – Lee Daniel Crocker Oct 28 '15 at 19:28

2 Answers2

12

strlen iterates until a null byte is found. malloc leaves the allocated space uninitialized, so a null byte may occur randomly. After all, it's undefined behavior due to the access of uninitialized memory.

Determining the size of a mallocated block alone is not possible. Store the size in seperate variables like Lsize and Rsize.


Notes:

  • don't cast the result of malloc
  • multiplying by sizeof(char) is redundant as sizeof(char) == 1
  • use free after malloc
  • the corresponding format specifier for size_t, a.k.a. "return type of strlen and the sizeof operator" is %zu; %d is used on ints1

1 as @chux noted in the comments to this answer

Community
  • 1
  • 1
cadaniluk
  • 15,027
  • 2
  • 39
  • 67
  • 3
    `sizeof(char)` is pointless but `sizeof(L)` is not since that will work correctly even if the type of `L` is changed to something else such as `wchar_t`. Type names should almost never be passed to `sizeof`. – Carey Gregory Oct 28 '15 at 19:01
  • 2
    Suggested note to a fine answer: `printf("longueur de L: %d\n",strlen(L));` is UB - should be `%zu`. `strlen()` returns a `size_t`, just like the type `malloc(size_t n)` takes. – chux - Reinstate Monica Oct 28 '15 at 19:23
  • Thank you for the clarification. I don't think that the problem is caused but a non initialization. Even when I use the data, this problem happens. For example when I reserved 2 * sizeof(char), I have always a third character in the string. Or maybe, the right thing to do is to initialize it with NULL. – White Oct 30 '15 at 09:32
  • 1
    @White Uhm, yes, the problem **is** caused by the access of uninitialized memory, just as I and the creator of the other answer mentioned. It's undefined behavior. Randomness at play (from the point of view of the C standard). – cadaniluk Oct 30 '15 at 09:37
2

As someone partially mentioned, strlen() converts the input fed to it into the correct memory location then that location is incremented by 1 until the null character is found. The problem with trying to use strlen() on a pointer from a malloc() call is that the data returned at the returned pointer can be anything depending on how your OS handles memory.

If you want your pointers to reference a guaranteed set of null characters when allocating memory, you can use this code:

L = calloc(1,mid+1); 
R = calloc(1,n - mid+1); 

Then at least when you use strlen(), you'll get a zero.

If you must use malloc(), then you can use this code:

L = malloc(1,mid+1); 
R = malloc(1,n - mid+1); 
memset(L,0,mid);
memset(R,0,n - mid);

In both pieces of code, I assumed L and R are declared as char*.

and definitely use free() on all memory allocated with calloc and malloc or you can expect a memory leak which could lead into you restarting your computer.

If you want to put in a fixed number of bytes in memory in a quick way, use this after allocating memory:

memset(L,x,mid);
memset(R,x,n - mid);

but change x to any value other than zero or it will be null.

Here's a sample program that does more like what you expect:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(){
  int size=10;
  char* a=calloc(1,100); // allocate 100 null's and store pointer to them at 'a'
  printf("%d \n",size); // print wanted size
  printf("%d \n",strlen(a)); // print length of memory space which = 0
  memset(a,'A',size); // put 10 A's at the beginning of allocated memory
  printf("%d \n",strlen(a)); // print length again which now = 10
  printf("%s \n",a); // print memory (which is 10 A's)
  free(a); // free the memory
  return 0; 
}

The above compiled fine in my compiler with no warnings even with the compiler options -Wall and -Wextra enabled.

Mike -- No longer here
  • 2,064
  • 1
  • 15
  • 37