0

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?

imll
  • 321
  • 3
  • 13
  • Where are you assigning or allocating memory for the two strings that are the elements of the `host_ip[]` array? You've declared this array but that's all. – Adrian Mole Sep 21 '19 at 16:26
  • I thought that by writing `char *my_conf[1]` I would create something like: `my_conf = ["conf1"]`. In other words, I would be creating a pointer that would point to the beginning of an array with 1 value (this value could have any size). Maybe this is not what happens... – imll Sep 21 '19 at 16:59
  • 3
    `sizeof(conf)` gives you size of the pointer, not size of what it points to. And `sizeof(*conf)` would give you size of char, ie. 1. You have to pass the length as parameter, or use `strlen` in the function. – hyde Sep 21 '19 at 17:21
  • https://re2c.org/manual/manual.html gives an example of using s-tags to parse an IPv4 IP very nicely. – Neil Sep 21 '19 at 18:14

2 Answers2

2

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]);
1

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