0

I'm using the gcc compiler I installed which I run from my cmd (write in the editor visual code) & for debugging I also installed visual studio. It's my second semester and I just learned about malloc/calloc etc.

so the line:

ch_pointer = (char *)malloc(length * sizeof(char));

in my gcc compiler gives in return when I use strlen(ch_pointer), 2 or 4 as an answer.

If I use a number too big (example 100) for length it also just says strlen(ch_pointer) == 0.

It works perfectly fine if I write it in visual studio as:

ch_pointer = (char *)malloc(((length + 1) * sizeof(char)) / 2 - 1);

and that's the only case it worked perfectly.

get_number() function is fine it's just making sure you will type an int type.

void main() {
    char *ch_pointer = '\0';
    int length = 0;
    printf("Please write down your sentence length in characters (including spaces): ");
    length = get_number();

    ch_pointer = (char *)malloc(((length + 1) * sizeof(char)) / 2 - 1); 
    ch_pointer[strlen(ch_pointer) - 1] = '\0';

    printf("Please write down your sentence: ");
    for (int filling = 0; filling < strlen(ch_pointer); filling++)
        scanf(" %c", &ch_pointer[filling]);
    for (int printing = 0; printing < strlen(ch_pointer); printing++)
        printf("%c", ch_pointer[printing]);

    free(ch_pointer);
}

For both compilers to work the same if I write down 4 or even 100 to get an array length 5 or 101 that ends in '\0' & let me type and print perfectly:

length = 4
strlen(ch_pointer) == 4

or

length = 100
strlen(ch_pointer) == 100
chqrlie
  • 131,814
  • 10
  • 121
  • 189
barakadax
  • 47
  • 9
  • Why are you allocating `((length + 1) * sizeof(char)) / 2 - 1` bytes of memory? It should be `ch_pointer = malloc(length + 1);` – Weather Vane Apr 17 '19 at 07:06

2 Answers2

2

There's a fundamental misunderstanding here: strlen doesn't know a thing about the allocated size of the array you pass in; it just walks it until it finds a null character, and returns how many characters it had to skip.

As malloc returns a pointer to uninitialized memory, its content is unpredictable, so calling strlen over it is undefined behavior - in the worst case where the memory block has no zero in it, it will even go on reading outside it, hopefully crashing the program.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
1

The problem is, malloc() returns a pointer to the allocated memory, the content of which is indeterminate.

Quoting C11, chapter 7.22.3.4

The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.

That said, for the strlen() from chapter 7.24.6.3,

The strlen function computes the length of the string pointed to by s.

and

The strlen function returns the number of characters that precede the terminating null character.

So, strlen() experts the argument to be a string.

Now, by definition, the memory pointed to by the pointer returned by malloc() does not guarantee a null terminator to be present anywhere in the memory. Thus, you cannot run strlen() on that. You'll most likely invoke undefined behaviour by memory overrrun.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 1
    I feel stupid, thank you very much for clarifying this, will use: while( ch_pointer[something] != '\0') or use the length the user writes, thanks very much – barakadax Apr 17 '19 at 06:50
  • 1
    @barakadax: `while( ch_pointer[something] != '\0')` will be just as undefined behavior. You must write values to the bytes pointed to by `ch_pointer`. Conversely, allocating the memory with `calloc()` returns a block with all bytes initialized to `0`, hence `strlen(ch_pointer)` would return `0`. – chqrlie Apr 17 '19 at 06:57