Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

string doesn't end at NULL but still behaves normally, why?

Tags:

c

string

pointers

In the following code, I copy a string in to a char* str, which is 10 characters long, using strncpy().

Now according to strncpy() manual, "Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null terminated. " which is exactly what happens here.

The source string is 26 charcters long and I have copied 10 characters, hence no null character is placed at then end of str.

But when I print the contents of str, starting from 0 until I get '\0', it behaves normally.

Why? When there is no '\0' placed at the end then why does the loop stop at the correct place?

What I understand is that it should give "Segmentation fault" or at least it shouldn't stop there and keep printing some garbage values.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 10

int main()
{
    char *str ;
    str = malloc( sizeof( char ) * SIZE );
    if( str == NULL ) 
        exit( 1 );
    memset( str, 0, sizeof( char ) * SIZE );

    strncpy( str, "abcdefghijklmnopqrstuvwxyz", sizeof( char ) * SIZE );

    unsigned int index;
    for( index = 0; str[ index ] != '\0' ; index++ ) {
        printf( "str[ %u ] has got : %c \n ", index, str[ index ] );
    }

    return 0;
}

Here is the output :

 str[ 0 ] has got : a
 str[ 1 ] has got : b
 str[ 2 ] has got : c
 str[ 3 ] has got : d
 str[ 4 ] has got : e
 str[ 5 ] has got : f
 str[ 6 ] has got : g
 str[ 7 ] has got : h
 str[ 8 ] has got : i
 str[ 9 ] has got : j

Any help will be appreciated.

EDIT

Is there a proper way to check whether a string ends at '\0' or not? I always thought the above loop to be the ultimate test, but now it seems it isn't.

Lets say we get a string from some function developed by other programmer. Now how will we know that it ends at correct place with '\0'. May be it doesn't, then it will go beyond the actual size until we get some '\0'. We can never know the actual size of the string.

So how do we tackle such situation?

Any suggestion?

like image 422
Andrew-Dufresne Avatar asked Sep 23 '09 07:09

Andrew-Dufresne


People also ask

What happens if a string does not have a null at the end?

Technically, if there's no null terminator then it's not a string. You won't be able to call any library functions that require null terminated strings and expect a valid result.

Do all strings end with null?

All strings in code (delimited by double quotes "" ) are automatically null-terminated by the compiler.

Why do strings end with null character?

Because a null takes one byte, whereas storing the length of the string with the string itself could take multiple bytes. Memory was scarce back in the day, so the smaller solution won out.

Are strings automatically null-terminated?

The things that are called "C strings" will be null-terminated on any platform. That's how the standard C library functions determine the end of a string. Within the C language, there's nothing stopping you from having an array of characters that doesn't end in a null.


1 Answers

It just happens that there's a null byte right beyond the end of allocated block.

Most likely malloc() allocates more memory and puts so-called guard values that happen to contain null bytes or it puts some metadata to be used by free() later and this metadata happens to contain a null byte right at that position.

Anyway you should not rely on this behaviour. You have to request (malloc()) one more byte for the null character so that the null character location is also legally allocated to you.

There's no portable way to test if a string is null-terminated properly. It can happen that once you're past the end of allocated block your program will just crash. Or it can happen that there is a null character somewhere beyond the end of block and you overwrite memory beyond the end of block later when manipulating the misinterpreted string.

Ideally you need some function that would check if a given address is allocated to you and belongs to the same allocation as another given address (perhaps start of the block). This would be slow and not worth it and there's no standard way for doing this.

In other words, if you encounter a string which is meant to be null-terminated but really isn't you're screwed big time - your program will run into undefined behaviour.

like image 81
sharptooth Avatar answered Sep 28 '22 00:09

sharptooth