освобождение памяти malloc приводит к тому, что другая память malloc может быть мусором - PullRequest
0 голосов
/ 11 октября 2018

Я пытаюсь выучить C, и одна из вещей, которые я нахожу хитрыми, это струны и манипулирование ими.Я думаю, что понимаю основы этого, но я принял как должное многие из того, что может войти в строки в JS или PHP (откуда я).

Я пытаюсь сейчас написатьфункция, которая разбивает строку в массив на основе разделителя, используя strtok.Подобно реализации PHP explode().

Вот код:

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

char **explode(char *input, char delimiter) {
    char **output;
    char *token;
    char *string = malloc(sizeof(char) * strlen(input));
    char delimiter_str[2] = {delimiter, '\0'};
    int i;
    int delim_count = 0;

    for (i = 0; i < strlen(input); i++) {
        string[i] = input[i];
        if (input[i] == delimiter) {
            delim_count++;
        }
    }
    string[strlen(input)] = '\0';

    output = malloc(sizeof(char *) * (delim_count + 1));
    token = strtok(string, delimiter_str);

    i = 0;
    while (token != NULL) {
        output[i] = token;
        token = strtok(NULL, delimiter_str);
        i++;
    }

    // if i uncomment this line, output gets all messed up
    // free(string);

    return output;
}

int main() {
    char **row = explode("id,username,password", ',');
    int i;

    for (i = 0; i < 3; i++) {
        printf("%s\n", row[i]);
    }

    free(row);
    return 0;
}

У меня есть вопрос, почему, если я пытаюсь free(string) в функции, вывод будет испорчени если я делаю это неправильно в первую очередь.Я считаю, что просто не правильно отображаю память в своей голове, и поэтому я не понимаю проблему.

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

вы неправильно понимаете, что делает strtok, он не создает новых строк, он просто возвращает указатель на разные части исходной строки.Если вы затем освободите эту строку, все сохраненные вами указатели станут недействительными.Я думаю, что вам нужно

while (token != NULL) {
    output[i] = strdup(token);
    token = strtok(NULL, delimiter_str);
    i++;
}

strdup будет выделен и скопировать новую строку для вас

0 голосов
/ 11 октября 2018

В output вы сохраняете указатели, которые указывают на string, поэтому при освобождении string вы освобождаете память, на которую указывают указатели output.

Недостаточно сохранитьуказатели.Вам придется скопировать фактические строки.Для этого вам нужно выделить память для output другим способом.

...