Tahmin Ahmed
Tahmin Ahmed

Reputation: 41

Appending strings results in "realloc(): Invalid pointer"

I have a function append_string, which appends str2 to str1:

void append_string(char* str1, char* str2) {
    int    new_length = strlen(str1)+strlen(str2);
    size_t new_size = sizeof(char)*(new_length);
    str1 = (char*) realloc(str1, new_size);
    strcat(str1, str2);
}

As shown in the function, I'm trying to increase the size using a the combined size of the strings.

Whenever I call append_str("", "adc");, I get "realloc(): Invalid pointer"

What did I do wrong?

Upvotes: 0

Views: 81

Answers (1)

chux
chux

Reputation: 154315

At least these problems:

Attempting to reallocate something not allocated.

realloc(str1, new_size) attempts to reallocate the string literal "" leading to "realloc(): Invalid pointer".

Size off by 1

New size did not account for the null character.

// size_t new_size = sizeof(char)*(new_length);
size_t new_size = sizeof(char)*(new_length + 1);

Code loses the allocated pointer

Calling code lost the value of the new pointer str.

Weak type for sizing

Use size_t.


Instead, pass in an allocated pointer or NULL by its address.

void append_string(char** str, const char* appendage) {
  size_t new_length = strlen(*str) + strlen(appendage);
  size_t new_size = sizeof(char)*(new_length + 1);
  *str = realloc(*str, new_size);
  strcat(*str, appendage);
}

// Usage
char *s = malloc(1);
strcpy(s, "");
append_str(&s, "adc");
puts(s);

Advanced issues include:

  • What to do if realloc() returns NULL?

  • How to handle appendage overlapping str?

  • Do not use strcat(). Avoid slow code. Better to retain the original string length and copy from there.

      void append_string(char** str, const char* appendage) {
        size_t str_len = *str ? strlen(*str) : 0;
        size_t app_len = strlen(appendage);
        void *p = realloc(*str, str_len + app_len + 1);
        if (p == NULL) {    
          // Handle Error - various approaches
          free(*str);
          *str = NULL;
        } else {        
          strcpy(*str + str_len, appendage);
        }
      }
    

Still need to handle case when appendage overlaps *str.

    void append_string_when_overlap_possible(char** str, const char* appendage) {
      size_t str_len = *str ? strlen(*str) : 0;
      size_t app_len = strlen(appendage);
      char *p = malloc(str_len + app_len + 1);
      if (p == NULL) {    
        // Handle Error - various approaches
        free(*str);
        *str = NULL;
      } else {        
        if (*str) {
          strcpy(p, *str);
        }
        strcpy(p + str_len, appendage);
        free(*str);
        *str = p;
      }
    }

Upvotes: 4

Related Questions