Home > Software engineering >  Issues reallocating memory to string
Issues reallocating memory to string

Time:06-01

New to c and trying to learn. Here I tried to create a function that copies a string until first space using dynamic memory allocation and byref. Seems like I'm doing something wrong with the way I used realloc. Can you help me figure out what is wrong with the way I used dynamic memory allocation?

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

void f1(char **c, char *s);

int main() {
    char * s = "this is an example";
    char *c;

    c =(char *) malloc(sizeof(char));
    f1(&c,s);
    free(c);
}

void f1(char **c, char *s)
{
    int i=0;
    while ((s[i])!=' ')
    {
        (*c)[i]=s[i];
        i  ;
        (*c)=(char *)realloc ((*c),sizeof(char)*i);
    }

    (*c)[i]='\0';
    printf("\n%s\n",*c);

}

CodePudding user response:

void f1(char** r, char* s) 
{
   // find size of new buffer
   size_t len = 0;
   while(s[len] != '\0' && s[len] != ' ') len  ;

   *r = (char*)malloc(len   1);

    memcpy(*r, s, len);

    (*r)[len] = '\0';
}

CodePudding user response:

Before the function call there was already allocated memory for one character

c =(char *) malloc(sizeof(char));

In the first iteration of the while loop

int i=0;
while ((s[i])!=' ')
{
    (*c)[i]=s[i];
    i  ;
    (*c)=(char *)realloc ((*c),sizeof(char)*i);
}

this memory was filled

    (*c)[i]=s[i];

and then again there was allocated memory only for one character

    (*c)=(char *)realloc ((*c),sizeof(char)*i);

because in the first iteration of the loop i becomes equal to 1. So in the second iteration of the loop there is an attempt to write outside the allocated memory that results in undefined behavior.

You need to write at least like

    *c = realloc ( *c, i   1);

Also it will be more safer to use an intermediate pointer as for example

char *tmp = realloc ( *c, i   1);
if ( tmp != NULL ) *c = tmp;

but in this case you will need also to change the function logic.

And the function should be declared like

int f1( char **c, const char *s);

and the condition of the should be changed like

while ( s[i] != '\0' && s[i] !=' ' )

Using your approach the program can look the following way.

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

int f1( char **s1, const char *s2 );

int main( void ) 
{
    const char *s = "this is an example";
    char *t = malloc( sizeof( char ) );

    if ( t != NULL )
    {
        t[0] = '\0';
        f1( &t, s);
        puts( t );
    }

    free( t );
}

int f1( char **s1, const char *s2 )
{
    int success = 1;

    for ( size_t i = 0; success && s2[i] != '\0' && !isblank( ( unsigned char )s2[i] ); i   )
    {
        char *tmp = realloc( *s1, i   2 );

        success = tmp != NULL;

        if ( success )
        {
            *s1 = tmp;
            ( *s1 )[i] = s2[i];
            ( *s1 )[i 1] = '\0';
        }
    }

    return success;
}

The program output is

this

However such an approach with many memory reallocations is inefficient.

I would write the program the following way

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

char * f1( const char *s, const char *delim );

int main( void ) 
{
    const char *s = "this is an example";
    char *t = f1( s, " \t" );

    if ( t != NULL )
    {
        puts( t );
    }

    free( t );
}

char * f1( const char *s, const char *delim )
{
    size_t n = strcspn( s, delim );

    char *result = malloc( n   1 );

    if ( result != NULL )
    {
        result[n] = '\0';
        memcpy( result, s, n );
    }

    return result;
}

Again the program output is

this

CodePudding user response:

As @UnholySheep mentioned the i I used to allocate memory was too small. Changed to (*t) = (char *)realloc((*t),(i 1)*sizeof(char)); and it worked.

CodePudding user response:

In this code, there is a committed mistake regarding using a double pointer. A double pointer should be used only to create an array of arrays. According to your purpose, you should use a single pointer to represent the array to copy to. Also, you need to create another function that counts the length of the string you want to copy before creating the string to copy to.

  • Related