Free(): invalid pointer in C program - c

I am executing following C program and getting runtime error as "free(): Invalid Pointer"
#include<stdio.h>
#include<stdlib.h>
static void freeArgs(char** args);
int main()
{
char** argv = calloc(4, 10);
int argc = 0;
argv[argc++]="yogita";
argv[argc++] ="negi";
argv[argc] = NULL;
freeArgs(argv);
return 0;
}
static void freeArgs(char** args)
{
char** af = args;
for (; *af; af++)
free(*af);
free(args);
}
Can anyone suggest me the solution?

free(*af);
tries to free memory that was not allocated through malloc/calloc:
argv[argc++]="yogita";
"yogita" is a string literal, thus not dynamically allocated. You can't free its memory.

This call
char** argv = calloc(4, 10);
(Note:it seems you mean
char** argv = calloc( 4, sizeof( char * ) );
end note)
with the magic number 10 allocates dynamically only one extent of memory of the size 4 * 10 that is equal to 40. So you need to call the function free only one time for the allocated extent. That is how many times malloc or calloc was called the same number of times free should be called.
I suspect that you meant something like the following
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void freeArgs( char **args )
{
char **af = args;
while ( *af ) free( *af++ );
free( args );
}
int main(void)
{
enum { N = 4, LEN = 10 };
char **argv = calloc( N, sizeof( char * ) );
size_t argc = 0;
argv[argc] = malloc( LEN * sizeof( char ) );
strcpy( argv[argc++], "yogita" );
argv[argc] = malloc( LEN * sizeof( char ) );
strcpy( argv[argc++], "negi" );
freeArgs( argv );
return 0;
}

Related

strncat causes buffer overflow

how can I use strncat with heap objects?
Im trying to write a simple function to concatenate 2 strings together returning the result, however, I can not run it without making the return buffer very large (adding approximately an additional 5000 to its length) for it to not overflow.
I'm probably just using the strncat function incorrectly using heap objects instead of character arrays of fixed length. but I don't know how I would write it any other way.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *concatStrings(char *arg1, char *arg2) {
char *ret = malloc(strlen(arg1) + strlen(arg2));
strncpy(ret, arg1, strlen(arg1));
strncat(ret, arg2, strlen(arg2));
ret[strlen(arg1)+strlen(arg2)] = '\0';
return ret;
}
int main(int argc, char *argv[]) {
if (argc == 3) {
char *print = concatStrings(argv[1], argv[2]);
printf("\n%s", print);
free(print);
}
return 0;
}
For starters the function should be declared like
char * concatStrings( const char* arg1, const char* arg2 );
because the strings pointed to by the pointers arg1 and arg2 are not being changed within the function.
In this memory allocation
char *ret = malloc(strlen(arg1) + strlen(arg2));
you forgot to reserve memory for the null terminating character '\0'. You have to write
char *ret = malloc( strlen(arg1) + strlen(arg2) + 1 );
Using the magic number 10 in this call
strncpy(ret,arg1,10);
does not make a sense.
If instead you will write for example
strncpy(ret,arg1,strlen(arg1));
then the next call
strncat(ret,arg2,strlen(arg2));
will invoke undefined behavior because the call strncpy did not append the null terminating character '\0' to the string pointed to by the pointer ret.
It would be much better just to write at least
strcpy( ret, arg1 );
In any case your function implementation is inefficient. For example there are two times called the function strlen for the parameter arg2
char *ret = malloc(strlen(arg1) + strlen(arg2));
//...
strncat(ret,arg2,strlen(arg2));
Also the call of strncat is also inefficient because the function needs to traverse the whole target string to find its terminating zero.
The function can be defined the following way
char * concatStrings( const char* arg1, const char* arg2 )
{
size_t n1 = strlen( arg1 );
char *ret = malloc( n1 + strlen( arg2 ) + 1 );
if ( ret != NULL )
{
strcpy( ret, arg1 );
strcpy( ret + n1, arg2 );
}
return ret;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * concatStrings( const char* arg1, const char* arg2 )
{
size_t n1 = strlen( arg1 );
char *ret = malloc( n1 + strlen( arg2 ) + 1 );
if ( ret != NULL )
{
strcpy( ret, arg1 );
strcpy( ret + n1, arg2 );
}
return ret;
}
int main(void)
{
const char *argv1 = "Hello ";
const char *argv2 = "World!";
char *print = concatStrings( argv1, argv2 );
if ( print != NULL ) puts( print );
free( print );
return 0;
}
The program output is
Hello World!
It would be even better to substitute the first call of strcpy for memcpy within the function. That is the function can also look like
char * concatStrings( const char* arg1, const char* arg2 )
{
size_t n1 = strlen( arg1 );
char *ret = malloc( n1 + strlen( arg2 ) + 1 );
if ( ret != NULL )
{
memcpy( ret, arg1, n1 );
strcpy( ret + n1, arg2 );
}
return ret;
}
The first problem is, that you don't allocate enough memory, because in C a string is terminated by a 0-byte so it should be
char *ret = malloc((strlen(arg1) + strlen(arg2))+1);
And of couse you should check if malloc worked.
if (!ret)
// error
The second problem is, that you use strncpy with a hardcoded length here.
Just use strcpy because you already allocated enough memory.
You can also use strcat for the same reason. strncat doesn't provide any additionaly benefit, and in fact makes the code slower because you, again, call strlen.
This
ret[10 + strlen(arg2)] = '\0';
is not needed at all. In fact its potentially dangerous if arg1 is less then 10 characters.
I forget snprintf existed and thought I had to use either strcpy strcat or some other string or memory management function to do this
char* concatStrings(char* arg1, char*arg2){
size_t n1 = strlen(arg1), n2 = strlen(arg2);
char *ret = malloc(n1 + n2 + 1);
snprintf(ret,n1 + n2 + 1, "%s%s", arg1, arg2);
return ret;
}
Problems
Not allocating space for the null character. Off by 1.
strncpy(ret, arg1, strlen(arg1)) does not null character terminate ret, so the next strncat(ret,... is undefined behavior as ret needs to point to a string.
Some alternatives:
// Via sprintf
// Good compilers will emit efficient code
// and not perform the usual parsing overhead of *printf format at run time
char *concatStrings_alt1(const char *arg1, const char *arg2) {
char *ret = malloc(strlen(arg1) + strlen(arg2) + 1);
sprintf(ret, "%s%s", arg1, arg2);
return ret;
}
// Via memcpy
char *concatStrings_alt2(const char *arg1, const char *arg2) {
size_t len1 = strlen(arg1);
size_t size2 = strlen(arg2) + 1;
char *ret = malloc(len1 + size2);
memcpy(ret, arg1, len1);
memcpy(ret + len1, arg2, size2);
return ret;
}

Create a 2d array of strings using dynamically allocation in c

I have to store some strings given in the args of a c code. I iterate over them but I can't store them properly because I don't know the length of those and neither their number. The better method should be a 2d array of pointers, so I can dynamically allocate memory for every new string. The problem is that I'm new on c and I have a lot of confusion about that technique. I tried to initialize a double pointer and use a function to insert elements, it allocates space for another column(new string) and set the length(size of string).
char** files;
int files_i=0;
void insert(char** root,char[] str)
{
root=(char **)malloc(sizeof(char *));
root[files_i]=(char *)malloc(sizeof(char)*sizeof(str));
root[files_i*sizeof(str)]=str;
i++;
}
I pass to the function the double pointer and the string I need to "append". It's not working and I have also really big doubts on how to iterate over that...
What you need is the following
char **files = NULL;
size_t files_i = 0;
//...
int insert( char ***root, const char str[], size_t i )
{
char *p = malloc( strlen( str ) + 1 );
int success = p != NULL;
if ( success )
{
char **tmp = realloc( *root, ( i + 1 ) * sizeof( char * ) );
if ( success )
{
strcpy( p, str );
tmp[i] = p;
*root = tmp;
}
else
{
free( p );
}
}
return success;
}
and then in the caller you can write for example
if ( insert( &files, some_string, files_i ) ) ++files_i;
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int insert( char ***root, const char str[], size_t i )
{
char *p = malloc( strlen( str ) + 1 );
int success = p != NULL;
if ( success )
{
char **tmp = realloc( *root, ( i + 1 ) * sizeof( char * ) );
if ( success )
{
strcpy( p, str );
tmp[i] = p;
*root = tmp;
}
else
{
free( p );
}
}
return success;
}
int main(void)
{
char **files = NULL;
size_t files_i = 0;
if ( insert( &files, "Hello", files_i ) ) ++files_i;
if ( insert( &files, "World", files_i ) ) ++files_i;
for ( size_t i = 0; i < files_i; i++ )
{
puts( files[i] );
}
for ( size_t i = 0; i < files_i; i++ )
{
free( files[i] );
}
free( files );
return 0;
}
Its output is
Hello
World
use strlen(str) instead of sizeof(str) for calculating the string length.
root[files_i]= malloc(strlen(str) + 1); // +1 for null character at the end of the string
if(!root[file_i]) {return;}
if you want to copy string, use strcpy instead of using = operator. Or use strdup (if you use strdup, you do not need to allocate memory for character pointer).
strcpy(root[files_i],str); // copy string str to "file_i" position of array root
if you use the global counter file_i, you should use realloc for root, because the size of root has to be vary (i think it's typo, the i++ should change to file_i++ ?).
root= realloc(root, sizeof(char *) * (file_i + 1));
// do not forget to check the return value of malloc or realloc function.
if(!root) {return;}
Do not cast malloc or realloc function. See at Do I cast the result of malloc?

C function prototype: \\char *strinv(const char *s);

char *strinv(const char *s); //that's the given prototype
I'm a bit insecure about the *strinv part. Does it mean that the function is automatically dereferenced when called? Or that the function is defined as a pointer?
Thanks in advance for clarification.
This function declaration
char * strinv(const char *s);
declares a function that has the return type char *. For example the function can allocate dynamically memory for a string and return pointer to that string.
Here is a demonstrative program that shows how the function for example can be defined.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * strinv(const char *s)
{
size_t n = strlen( s );
char *t = malloc( n + 1 );
if ( t != NULL )
{
size_t i = 0;
for ( ; i != n; i++ ) t[i] = s[n-i-1];
t[i] = '\0';
}
return t;
}
int main(void)
{
const char *s = "Hello Worlds!";
char *t = strinv( s );
puts( t );
free( t );
return 0;
}
The program output is
!sdlroW olleH
A declaration of a pointer to the function can look the foolowing way
char * ( *fp )( const char * ) = strinv;
To dereference the pointer and call the pointed function you can write
( *fp )( s );
though it is enough to write
fp( s );

C Increase char array of char array size

I have a char array of char array like so:
char my_test[2][10];
As you can see I have a length of 2 and then 10. If I need to increase the first char array (2), how can this be done dynamically?
For example, half way through my application char[2] might be in use so therefore I need to use position 3 in the char array. I would then end up with this:
char store[3][10];
But keeping the data originally store in:
char store[0][10];
char store[1][10];
char store[2][10];
You should dynamically allocate memory for the array using standard C functions malloc and realloc declared in header <stdlib.h>.
Here is a demonstrative program that shows how the memory can be allocated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
int main(void)
{
size_t n = 2;
char ( *my_test )[N] = malloc( n * sizeof( char[N] ) );
strcpy( my_test[0], "first" );
strcpy( my_test[1], "second" );
for ( size_t i = 0; i < n; i++ ) puts( my_test[i] );
putchar( '\n' );
char ( *tmp )[N] = realloc( my_test, ( n + 1 ) * sizeof( char[N] ) );
if ( tmp != NULL )
{
my_test = tmp;
strcpy( my_test[n++], "third" );
}
for ( size_t i = 0; i < n; i++ ) puts( my_test[i] );
free( my_test );
return 0;
}
The program output is
first
second
first
second
third
char my_test[2][10];
is compile-time constant, which means that the required memory to use that array is carved to the stone already before your application starts. So you will never be able to change it's size.
You'll have to use DYNAMIC allocation. Check for something called malloc and free in case you are really working with C, or with C++ new and delete are what you need. You'll also need to learn about pointers.

Can I free only a part of a string?

I am filling up a string of characters and I double its size from time to time.
When I finish, I would like to free unused memory.
void fun (char **str, size_t *len) {
size_t lsi; //last_significant_index
//filling up the str and reallocating from time to time.
//*len is storing the total size of allocated memory at this point
// idea #1
free((*str)[lsi + 1]);
// idea #2
for(size_t i = lsi + 1; i < *len; i++) {
free(&(*str)[i]);
}
}
None of these ideas seem to work however
Is it even possible to do it? If so, how?
Details:
I am using this function to reallocate my strings:
static void increase_list_size(char **list, size_t *list_len)
{
size_t new_list_size = (*list_len + 1) * 2; // I am not allocating my list at the declaration, so *list_len initially equals 0.
char *new_list = malloc(sizeof(char) * new_list_size);
for (size_t i = 0; i < *list_len; i++)
{
new_list[i] = (*list)[i];
}
if (list != NULL) // I don't want to free an empty list (it wasn't allocated at the declaration!
{
free(*list);
}
(*list) = new_list;
*list_len = new_list_size;
}
As you can see, I am allocating two-times more memory every time - that's why I wanted to free unused memory at the end.
I thought there was some kind of a tricky way to do it, since I felt that you can only use free() to free whole memory block.
No, you can only free() pointers that have been returned by malloc().
You want to use realloc() to change the allocated memory size to a smaller (as well as larger) size. The contents of the array will be preserved.
Example:
#include <stdlib.h>
int main() {
char *str = malloc(100);
...
str = realloc(str, 50);
...
free(str);
}
Remember to check the return value of realloc() (as well as the one of malloc()) to ensure that the (re)allocation has not failed.
You can only free a pointer that is the result of malloc or realloc. You can't reduce the size of an allocation by freeing at an arbitrary offset from it. But you can realloc it to a smaller size: realloc(*str, lsi).
one way is to create a new string and use only space required and copy the content to this one. now you can free the previous one.
I will use this is realloc() is not allowed (sometimes in homework)
the other way is realloc() as others suggested.
You can use standard C function realloc declared in header <stdlib.h>
For example
char *s = malloc( 100 );
strcpy( s, "Hello world" );
char *p = realloc( s, strlen( s ) + 1 );
if ( p != NULL ) s = p;
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
char *s = malloc( 100 );
strcpy( s, "Hello world" );
char *p = realloc( s, strlen( s ) + 1 );
if ( p != NULL ) s = p;
puts( s );
free( s );
return 0;
}
The program output is
Hello world
Or if you want to write a separate function then it can look the following way
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void resize( char **s, size_t n )
{
char *p = realloc( *s, n );
if ( p != NULL ) *s = p;
}
int main( void )
{
char *s = malloc( 100 );
strcpy( s, "Hello world" );
resize( &s, strlen( s ) + 1 );
puts( s );
free( s );
return 0;
}
Also you can use POSIX function strdup

Resources