realloc, кажется, не перераспределяет память - PullRequest
0 голосов
/ 31 мая 2018

Мне нужно динамически добавлять символ в строку, поэтому я использую realloc(), чтобы добавить больше памяти, когда мне это нужно.

Я новичок в C (из Python), поэтому яЯ много читал, и это было лучшее, что я мог сделать:

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

void append_to(char *array, char value) {
    size_t buffer = (strlen(array) * sizeof(char)) + sizeof(char);
    char *new_array = realloc(array, buffer);
    if (new_array == NULL) {
        printf("CRITICAL ERROR\n");
        exit(-1);
    }
    array = new_array;
    int position = strlen(array);
    array[position] = value;
}

int main() {
    char *list = malloc(sizeof(char));
    for (int i = 1; i < 26; i++){
        append_to(list, 'a');
        printf("%d -> %s\n", i, list);
    }
}

Это всего лишь пример, демонстрирующий проблему.Код работает без сбоев до итерации 24, см. Ниже:

1 -> a
2 -> aa
[...] //omitted
23 -> aaaaaaaaaaaaaaaaaaaaaaa
24 -> aaaaaaaaaaaaaaaaaaaaaaaa
25 -> 

Чего мне не хватает?

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Вы не получили array в качестве двойного указателя, поэтому вы не можете переназначить указатель вызывающего, когда realloc должен переместить выделение.

Чтобы исправить,

// Receive double pointer
void append_to(char **array, char value) {
    // Add dereferencing as needed
    size_t buffer = (strlen(*array) + 2) * sizeof(char);
    char *new_array = realloc(*array, buffer);
    if (new_array == NULL) {
        printf("CRITICAL ERROR\n");
        exit(-1);
    }
    *array = new_array;
    int position = strlen(*array);
    array[0][position] = value;
    array[0][position+1] = '\0'; // Explicitly NUL terminate, don't assume new memory is zeroed
}

int main() {
    char *list = malloc(sizeof(char));
    for (int i = 1; i < 26; i++){
        append_to(&list, 'a');  // Pass address of list
        printf("%d -> %s\n", i, list);
    }
}
0 голосов
/ 31 мая 2018

Сначала вы забыли добавить еще один символ NUL в конец вашей строки C.

Во-вторых, realloc может изменить расположение данных в памяти, но вы передали list в качестве значения, поэтомуперемещение не видно в случае перемещения данных.

Это должно выглядеть так:

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

void append_to(char **array, char value) { // pass pointer's address
    size_t buffer = (strlen(*array) * sizeof(char)) + sizeof(char) + sizeof(char); // one more to tackle the end of the string
    char *new_array = realloc(*array, buffer);
    if (new_array == NULL) {
        printf("CRITICAL ERROR\n");
        exit(-1);
    }
    *array = new_array;
    int position = strlen(*array);
    (*array)[position] = value;
    (*array)[position+1] = 0; // end of string
}

int main() {
    char *list = malloc(sizeof(char));
    list[0] = 0; // end of string
    for (int i = 1; i < 26; i++){
        append_to(&list, 'a'); // pass address of array so that it can be changed by the call
        printf("%d -> %s\n", i, list);
    }
    free(list); // always explicitly free unused resources
}
...