asifab
asifab

Reputation:

Realloc Problem

Thank you for looking, please ignore - all sorts of shenanigans are happening and I am trying to debug more.

=====================================

Can anyone explain this behavior of realloc?

Output:

before realloc start: testing%20encryp
before realloc app: '          '
realloc size: 27
after realloc: testing%20e
strlen(newstr): 11
newstr: testing%20e

Code:

char * strAppend(char * start, char * app)
{
  int i=strlen(start);
  int j=0;
  printf("before realloc start: %s\n", start);
  printf("before realloc app: '%s'\n", app);
  printf("realloc size: %i\n", i+strlen(app)+1);
  char * newstr = realloc(start, sizeof(char) * (i + strlen(app) + 1));
  printf("after realloc: %s\n", newstr);
  while(app[j] != '\0')
    newstr[i++] = app[j++];
  printf("strlen(newstr): %i\n", strlen(newstr));
  printf("newstr: %s\n", newstr);
  return newstr; }

It's deleting "ncryp" from start after the realloc; but that's not supposed to happen....

Edit: More Code, More Output

char * urlEncode(char * c)
{
#ifdef EBUG
  printf("urlEncode: Encoding '%s'\n", c);
#endif
  int len = strlen(c)+1;
  char * ret = malloc(sizeof(char) * len);
  memset(ret, 0, len);
  int z=0;
  char * escapee = malloc(sizeof(char) * 4);
  escapee[0] = '%'; escapee[3] = '\0';
  for(int i=0;i<strlen(c);i++)
    {
      printf("z = %i len = %i ret = %s\n", z, len, ret);
      if(z >= len)
        {
          ret = strAppend(ret, "          ");
          len += strlen("          ");
        }
      printf("z = %i len = %i ret = %s\n", z, len, ret);
      if ( (48 <= c[i] && c[i] <= 57) ||//0-9
           (65 <= c[i] && c[i] <= 90) ||//abc...xyz
           (97 <= c[i] && c[i] <= 122) || //ABC...XYZ
           (c[i]=='~' || c[i]=='!' || c[i]=='*' || c[i]=='(' || c[i]==')' || c[i]=='\'')
           )
        {
          ret[z++] = c[i];
        }
      else
        {
          char2hex(c[i], escapee);
          ret = strAppend(ret, escapee);
          z += 3;
        }
    }
  ret[z] = '\0';
  free(escapee);
#ifdef EBUG
  printf("urlEncode: Encoded string to '%s'\n", c);
#endif
  return ret;
}




urlEncode: Encoding 'testing encrypt'
z = 0 len = 16 ret =
z = 0 len = 16 ret =
z = 1 len = 16 ret = t
z = 1 len = 16 ret = t
z = 2 len = 16 ret = te
z = 2 len = 16 ret = te
z = 3 len = 16 ret = tes
z = 3 len = 16 ret = tes
z = 4 len = 16 ret = test
z = 4 len = 16 ret = test
z = 5 len = 16 ret = testi
z = 5 len = 16 ret = testi
z = 6 len = 16 ret = testin
z = 6 len = 16 ret = testin
z = 7 len = 16 ret = testing
z = 7 len = 16 ret = testing
before realloc start: testing
before realloc app: '%20'
realloc size: 11
after realloc: testing
strlen(newstr): 10
newstr: testing%20
z = 10 len = 16 ret = testing%20
z = 10 len = 16 ret = testing%20
z = 11 len = 16 ret = testing%20e
z = 11 len = 16 ret = testing%20e
z = 12 len = 16 ret = testing%20en
z = 12 len = 16 ret = testing%20en
z = 13 len = 16 ret = testing%20enc
z = 13 len = 16 ret = testing%20enc
z = 14 len = 16 ret = testing%20encr
z = 14 len = 16 ret = testing%20encr
z = 15 len = 16 ret = testing%20encry
z = 15 len = 16 ret = testing%20encry
z = 16 len = 16 ret = testing%20encryp
before realloc start: testing%20encryp
before realloc app: '          '
realloc size: 27
after realloc: testing%20encryp
strlen(newstr): 26
newstr: testing%20encryp
z = 16 len = 26 ret = testing%20encryp

Last Edit:

I have no idea what is going on at the moment. Different runs of the program with and without debug flags produce different output. I'm going back to the drawing board and looking for memory errors using valgrind.

Upvotes: 3

Views: 2224

Answers (4)

Mandrake
Mandrake

Reputation: 361

char * strAppend(char * start, char * app)
{
  int i=strlen(start);
  int j=0;
  printf("before realloc start: %s\n", start);
  printf("before realloc app: '%s'\n", app);
  printf("realloc size: %i\n", i+strlen(app)+1);
  char * newstr =(void*) realloc(start, sizeof(char) * (i + strlen(app) + 1));


  memset(newstr,'z',sizeof(char) * (i + strlen(app) + 1));
  printf("addres  %x\n",newstr);

  printf("after realloc: %s\n", newstr);
  while(app[j] != '\0')
    newstr[i++] = app[j++];

    //missing null terminating character
    newstr[i]=0;

  printf("strlen(newstr): %i\n", strlen(newstr));
  printf("newstr: %s\n", newstr);
  return newstr; 
  }

and in my system the address of the allocated string newstr is equal to start no matter what is the allocated size of 'start', aparently the system is reallocating the same position of the memory when it grows

Upvotes: 0

Andrew Y
Andrew Y

Reputation: 5107

Since it seems your original realloc problem has not been reproducible, I will dare to post a slightly refactored code that does what you are looking for. It makes two passes over the string, but in my opinion it should have a more predictable performance in terms of number of memory allocation calls performed - only once. It's also a bit shorter than yours.

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

int is_printable(char c) {
 return (48 <= c && c <= 57) ||//0-9
        (65 <= c && c <= 90) ||//abc...xyz
        (97 <= c && c <= 122) || //ABC...XYZ
        c == '~' || c =='!' || c== '*' ||
        c == '(' || c== ')' || c== '\'';
}

char *urlEncode(char *s) {
  char *ret, *c, *ct;
  int i, len;
  printf("urlEncode: Encoding '%s'\n", s);
  /* First pass - figure out how long the target string should be */
  len = 0;
  for(c=s; *c; c++) {
    if(is_printable(*c)) len++; else len += 3;
  }
  /* Don't forget we need to store terminating zero too */
  len++;
  printf("Current len: %d, target len: %d\n", strlen(s)+1, len);
  ct = ret = malloc(len);
  /* Second pass - copy/encode */
  for(c=s; *c; c++) {
    if(is_printable(*c)) {
      *ct++ = *c;
    } else {
      snprintf(ct, 4, "%%%02x", *c);
      ct += 3;
    }
  }
  *ct = 0; /* null-terminate the string */
  printf("Encoded string: %s\n", ret);
  return ret;
}

int main(int argc, char *argv[])
{
  urlEncode("testing encrypt");
  exit(1);
}

Upvotes: 1

CB Bailey
CB Bailey

Reputation: 791421

The first parameter to realloc must be a pointer that was previously returned by malloc, calloc or realloc and not subsequently freed.

If this isn't the case, anything might happen including what you've seen.

Where does start come from?

Edit: post your edit, you don't appear to be having a realloc problem!

Upvotes: 1

bashmohandes
bashmohandes

Reputation: 2376

I think what you are trying to do is to concatinate two strings start & app, if this is the case, you better use strncat function

#include <cstring>
char *strncat( char *str1, const char *str2, size_t count );

Upvotes: 1

Related Questions