DeeMax
DeeMax

Reputation: 260

C weird behavior when working with char*

I've got this function

Function *function_get_by_label(char *label_name) {     
    int new_len = strlen(label_name) - 9;
    char* name = malloc(sizeof(char) * new_len);
    for (int i = 0; i < new_len; i++) {
        name[i] = label_name[i];
    }

    return function_get(name);
}

however, when I try to debug this one with gdb, like display the name variable, I get the following

(gdb) display name
1: name = 0x610120 ""
(gdb) n
1: name = 0x610120 ""
1: name = 0x610120 "m"
1: name = 0x610120 "m"
1: name = 0x610120 "mu"
1: name = 0x610120 "mu"
1: name = 0x610120 "mul"
1: name = 0x610120 "mul"
1: name = 0x610120 "mult"
1: name = 0x610120 "mult"
1: name = 0x610120 "multi"
1: name = 0x610120 "multi"
1: name = 0x610120 "multip"
1: name = 0x610120 "multip"
1: name = 0x610120 "multipl"
1: name = 0x610120 "multipl"
1: name = 0x610120 "multiply2_function"

How is that possible that there's such a weird behavior? I tried to manipulate with these mallocs. I also tried to rewrite the function so I can give you an example how to reproduce it, but without a success.

Even more weird thing is, when I change allocated space in malloc to sizeof(char) * 99, the result is

(gdb) display name
1: name = 0x60f120 ""
(gdb) n
1: name = 0x60f120 ""
1: name = 0x60f120 "m"
1: name = 0x60f120 "m"
1: name = 0x60f120 "mu"
1: name = 0x60f120 "mu"
1: name = 0x60f120 "mul"
1: name = 0x60f120 "mul"
1: name = 0x60f120 "mult"
1: name = 0x60f120 "mult"
1: name = 0x60f120 "multi"
1: name = 0x60f120 "multi"
1: name = 0x60f120 "multip"
1: name = 0x60f120 "multip"
1: name = 0x60f120 "multipl"
1: name = 0x60f120 "multipl"
1: name = 0x60f120 "multiplyltiply2_function"

Upvotes: 0

Views: 123

Answers (2)

Christian Gibbons
Christian Gibbons

Reputation: 4370

You never null-terminate name, nor do you allocate enough space for the null terminator. Also, there's no need to loop through and copy the characters over that way. Since we know the source string is greater than the length we are copying, you should be able to do a simple memcpy (otherwise strncpy would be a good choice). So maybe something that looks like this:

Function *function_get_by_label(char *label_name) {     
    int new_len = strlen(label_name) - 8;
    char* name = malloc(sizeof(char) * new_len);
    memcpy(label_name, name, new_len-1);
    name[new_len-1] = '\0';

    return function_get(name);
}

Upvotes: 0

Paul Ogilvie
Paul Ogilvie

Reputation: 25286

You copy the string label_name to a new variable name that is 9 characters shorter. You copy all characters minus these last 9.

At this point, name is an unterminated C-string and all its storage has been used. In the machine's memory, there will be more memory after name but it is not yours and can have any data. Indeed, after you copied the last character (and your malloced memory was by pure chance zeroed), you see what is in the not-your-memory.

You pass name to a function function_get, however, that function doesn't know how long name is. If it would print it, it could print name correctly, or can print any data after it, until it encounters a null-character (if it encounters one at all; you don't know what is there). This is what is called undefined behavior.

When you allocate 99 characters with malloc you say it still shows "weird behavior". Indeed, because malloc doesn't initialize the memory so there could be any data in the memory. Although the memory now is yours (up to char 99), you still haven't terminated the string with a \0 character and you still have undefined behavior.

Lesson learned: terminate your strings with \0!!

Upvotes: 2

Related Questions