imll
imll

Reputation: 341

Wrong output after modifying an array in a function (in C)

I'm a C noob and I'm having problems with the following code:

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

void split_string(char *conf, char *host_ip[]){

    long unsigned int conf_len = sizeof(conf);
    char line[50];
    strcpy(line, conf);

    int i = 0;

    char* token; 
    char* rest = line; 

    while ((token = strtok_r(rest, "_", &rest))){
        host_ip[i] = token;
        printf("-----------\n");
        printf("token: %s\n", token);
        i=i+1;
    }
}

int main(){ 

    char *my_conf[1];

    my_conf[0] = "conf01_192.168.10.1";

    char *host_ip[2];
    split_string(my_conf[0], host_ip);

    printf("%s\n",host_ip[0]);
    printf("%s\n",host_ip[1]);
}

I want to modify the host_ip array inside the split_string function and then print the 2 resulting strings in the main.

However, the 2 last printf() are only printing unknown/random characters (maybe an address?). Any help?

Upvotes: 0

Views: 102

Answers (2)

Surendar Sekar
Surendar Sekar

Reputation: 97

You are storing address of local variable (line) which is in stack.Stack is LIFO and has valid data for local variables in its stack memory during its function life time.after that, the same stack memory will be allocated to another function's local variables. So, data stores in line【50】's memory will be invalid after coming out of string_split function

Upvotes: 1

There are 2 problems:

First, you're returning pointers to local variables. You can avoid this by strduping the strings and freeing in the caller.

Second:

On the first call to strtok_r(), str should point to the string to be parsed, and the value of saveptr is ignored. In subsequent calls, str should be NULL, and saveptr should be unchanged since the previous call.

I.e. you must NULL for the first argument after the first iteration in the loop. Nowhere is it said that it is OK to use the same pointer for both arguments. This is because the strtok_r is an almost drop-in replacement to the braindead strtok, with just one extra argument, so that you could even wrap it with a macro...

Thus we get

char *start = rest;
while ((token = strtok_r(start, "_", &rest))){
    host_ip[i] = strdup(token);
    printf("-----------\n");
    printf("token: %s\n", token);
    i++;
    start = NULL;  
}

and in the caller:

free(host_ip[0]);
free(host_ip[1]);

Upvotes: 2

Related Questions