Search code examples
cstringmemoryallocation

string Append function in C


I want to create a string append function, but when I want to print the function out it crash. I debugged it but I cannot find what could be the problem.

struct string {
    size_t length;
    size_t allocated;
    char* data;
};
string* Init(char* str) {
    string* s = malloc(sizeof(string));
    size_t strLen = strlen(str);
    s->data = (char*)malloc(strLen*2); //allocate 2x of the length
    memcpy(s->data,str,strLen);
    s->data[strLen] = '\0';
    s->length = strLen;
    s->allocated = 2*strLen;
    return s;
}
void AppendBack(string* str, string* new) {
    if(str->allocated < str->length + new->length) { //allocate more
        char* data = (char*)realloc(strGet(str),str->allocated*2);
        str->allocated = str->allocated*2;
        str->data = data;
        if(str->allocated < str->length + new->length) { //need more allocation
            AppendBack(str,new);
        }
    }
    str->length = str->length + new->length;
    for(int i = new->length; i >= 0; --i) {
        str->data[str->length - i] = new->data[new->length - i];
    }
    str->data[str->length] = '\0';
}

int main() {
    string* a = Init("abc");
    string* b = Init("1234fedfsdffghjkjhgfds3ghjk7345678juhzbfsdfsd");
    AppendBack(a,b);
    strPrint(a);
    return 0;
}

Edited code:

    char* strGet(string* str) {
        return str->data;
    }
    void strPrint(string* str) {
        printf("%s",strGet(str));
    }

I am sorry becuase I missed part of my code.


Solution

  • You have two bugs:

    1. You need to allocate an extra byte for the terminating zero.

    2. You need to return after calling AppendBack recursively or you corrupt the string.

    Here's working code:

    void AppendBack(string* str, string* new) {
        if(str->allocated < (str->length + new->length + 1)) { // NOTE: +1
            char* data = (char*)realloc(str->data,str->allocated*2); // removed call to strGet
            str->allocated = str->allocated*2;
            str->data = data;
            if(str->allocated < (str->length + new->length + 1)) { // NOTE: +1
                AppendBack(str,new);
                return; // NOTE: return here
            }
        }
        str->length = str->length + new->length;
        for(int i = new->length; i >= 0; --i) {
            str->data[str->length - i] = new->data[new->length - i];
        }
        str->data[str->length] = '\0'; // See? You need an extra byte for this
    }
    

    I removed the call to strGet because you didn't show us that code.