Reputation:
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
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
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
Reputation: 791421
The first parameter to realloc
must be a pointer that was previously returned by malloc
, calloc
or realloc
and not subsequently free
d.
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
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