Arthur Zopellaro
Arthur Zopellaro

Reputation: 158

realloc seems to not be reallocating memory

I need to dynamically append a char to a string, so I'm using realloc() to add more memory as I need it.

I'm new to C (coming from Python) so I've been reading a lot and this was the best I could do:

#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);
    }
}

This is just an example to showcase the issue. The code runs flawlessly until iteration 24, see below:

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

What am I missing?

Upvotes: 1

Views: 62

Answers (2)

ShadowRanger
ShadowRanger

Reputation: 155654

You didn't receive array as a double pointer, so you can't reassign the caller's pointer when realloc has to move the allocation.

To fix,

// 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);
    }
}

Upvotes: 2

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36441

First you forget to add another NUL char at the end of your c-string.

Second, realloc may change the memory location of the data, but you passed the list as value, so the relocation is not visible in the case of data relocation.

That should lokks like:

#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
}

Upvotes: 3

Related Questions