C pass char pointer by reference into a function executing strtok() but after returned print unexpected results

70 Views Asked by At

I want to test pass pointer by reference in C, below is my test code.

I expect the result to be: "World!", but after I executed, I found that the result is indeterminate.

void parse(char **p)
{
    char str[] = "Hello World!";

    char *token = strtok(str, " "); // token points to 'H'
    *p = strtok(NULL, " "); // *p (buf) points to 'W'

}

int main() 
{
    char *buf = (char*)malloc(20 * sizeof(char));

    buf = "How are you?";

    parse(&buf);

    printf("%s\n", buf);
}

My View:

(1) In main(): buf points to 'H' ("How are you?"'s first char 'H') (Suppose address of 'H' is 0x10)

(2) parse(&buf) makes pointer p points to buf (i.e. *p = buf = 0x10)

(3) After 2 times of strtok(), *p (buf) points to 'W' (Suppose address of 'W' is 0x20)

(4) Now, return to main(), buf points to 0x20


(5) I expect printf("%s\n", buf); should print "World!", but instead print something like "garbled text".

I have tried debugging, but I don't think I have mistaken anything above.

Can someone quell my doubts?

Thanks in advance.

1

There are 1 best solutions below

2
Vlad from Moscow On

This code snippet

char *buf = (char*)malloc(20 * sizeof(char));

buf = "How are you?";

produces a memory leak.

At first memory was dynamically allocated and its address was assigned to the pointer buf and then the pointer was reassigned with the address of the first character of a string literal. As a result the address of the allocated memory was lost.

Also you may not change a string literal. Any attempt to change a string literal results in undefined behavior,

You should write at least

strcpy( buf, "How are you?" );

As for the function then its local array with automatic storage duration

void parse(char **p)
{
    char str[] = "Hello World!";
    //...

will not be alive after exiting the function. So the pointer buf will have an invalid value.

The program can look for example the following way

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

void parse( char *s, char **p)
{
    *p = strtok( s, " " );
    *p = strtok(NULL, " ");
}

int main() 
{
    char str[] = "Hello World!";

    char *buf;

    parse( str, &buf );

    if ( buf ) printf("%s\n", buf);
}