how to free dynamic memory allocated inside function after finishing execution - c

how to free dynamic memory allocated inside function
after finishing execution
i allocated two char * str2R & str4R
and my function is
char * MMP(char * index)
{
char* str1= "AT+CMGR=";
char* str2R = (char *) malloc(1 + strlen(str1)+ strlen(index) );
strcpy(str2R, str1);
strcat(str2R, index);
char* str3="\r";
char* str4R = (char *) malloc(1 + strlen(str2R)+ strlen(str3) );
strcpy(str4R, str2R);
strcat(str4R, str3);
return str4R;
};
when i call
free(str2R);
free(str4R);
in main or in another file after calling the function
this error appears
error: str2R undeclared (first use in this function)
thanks in advance

You do not need to allocate two char* buffers, one will suffice. Then caller needs to free() the returned char* when it is done using it.
Try this:
char * MMP(char * index)
{
char* str1 = "AT+CMGR=";
char* str3 = "\r";
char* str2R = (char *) malloc(strlen(str1) + strlen(index) + strlen(str3) + 1);
if (str2R)
{
strcpy(str2R, str1);
strcat(str2R, index);
strcat(str2R, str3);
}
return str2R;
}
char *str = MMP("some value");
...
free(str);
With that said, the logic inside of MMP() would be better served using snprintf() instead of strcpy() and strcat():
char * MMP(char * index)
{
char* fmt = "AT+CMGR=%s\r";
char* str2R = NULL;
int len = snprintf(NULL, 0, fmt, index);
if (len > 0)
{
++len;
str2R = (char *) malloc(len);
if (str2R)
snprintf(str2R, len, fmt, index);
}
return str2R;
}

Related

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?
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;
}
}

How to copy char array in C without inner function

This is my code
char function(char *dst)
{
int i;
char *arr;
i = 0;
while(dst[i] != '\0')
{
arr[i] = dst[i];
i++;
}
dst[i] != '\0'
return(arr);
}
int main(void)
{
char a[] ="asdf"
printf("%s", function(a);
}
I want to copy *dst to empty *arr but my code didn't work.
I can't understand.
How can I copy array without inner function in C(ex_strcpy, memspy....)
Thank you
Apart from missing ; and making sure that the string being passed to the function is always a '\0' terminated one ( else the program will run into side effects strcpy causes ). and returning char* instead of char, you missed allocating memory for arr
// return char * instead of char
char* function(char *dst)
{
// Note - sizeof(dst) wont work
// Neither does sizeof(dst)/sizeof(char)
// allocate one extra for '\0'
size_t size_to_alloc = (strlen(dst) + 1) * (sizeof *arr);
char *arr = malloc( size_to_alloc );
char *p = arr;
for ( ; *dst ; p++, dst++)
*p = *dst;
*p = '\0';
return(arr);
}
If you want to dynamically copy an array, you'll need to allocate memory for the char array using malloc or other equivalent. Make sure you free the memory once you're done with it. I would suggest reading some posts on malloc and allocating memory in c.
This is probably a good place to start.
https://www.geeksforgeeks.org/dynamic-memory-allocation-in-c-using-malloc-calloc-free-and-realloc/
#include <stdio.h>
#include <stdlib.h>
char* function(char *dst, size_t length) {
int i;
// Allocating the memory needed for the char array.
char *arr = (char*) malloc (sizeof(char) * length);
i = 0;
while(dst[i] != '\0') {
arr[i] = dst[i];
i++;
}
arr[length - 1] = '\0';
return(arr);
}
int main(void) {
char a[] ="asdf";
// Getting length of the array
size_t length = sizeof(a) / sizeof(a[0]);
char* val = function(a, length);
printf("%s", val);
free(val);
}
You are missing the memory allocation and basically attempting to recode strdup. See below:
char *ft_strdup(const char *src)
{
char *dst;
int len;
len = 0;
while (src[len]) // no inner function
++len;
if (!(dst = malloc(sizeof(char) * (len + 1)))) // need 1 extra char to NULL terminate.
return NULL;
dst[len] = '\0';
while (--len > -1)
dst[len] = src[len];
return dst;
}
Note that it makes sense to code your own version of strdup and include it in your program library as this function is not part of the C Standard.
If there is a possibility of copying strings without using c functions, perhaps it can be done by doing what c functions do.
it may be interesting to see what strcpy does:
https://code.woboq.org/userspace/glibc/string/strcpy.c.html
char *
STRCPY (char *dest, const char *src)
{
return memcpy (dest, src, strlen (src) + 1);
}
infact it uses memcpy: https://code.woboq.org/gcc/libgcc/memcpy.c.html
and here the magic...
void *
memcpy (void *dest, const void *src, size_t len)
{
char *d = dest;
const char *s = src;
while (len--)
*d++ = *s++;
return dest;
}
and strlen: https://code.woboq.org/userspace/glibc/string/strlen.c.html
You can use memcpy() to copy memory directly, like in Memcpy, string and terminator and https://www.gnu.org/software/libc/manual/html_node/Copying-Strings-and-Arrays.html In C any string has to be terminated by \0 (sentinel value)
#include<stdio.h>
#include<string.h>
int main()
{
char source[] = "World";
char destination[] = "Hello ";
/* Printing destination string before memcpy */
printf("Original String: %s\n", destination);
/* Copies contents of source to destination */
memcpy (destination, source, sizeof(source));
/* Printing destination string after memcpy */
printf("Modified String: %s\n", destination);
return 0;
}
source : https://www.educative.io/edpresso/c-copying-data-using-the-memcpy-function-in-c

malloc, free, and memmove inside a subfunction

I want to use a subfunction to copy a char array. it is like this:
void NSV_String_Copy (char *Source, char *Destination)
{
int len = strlen(Source);
if (*Destination != NULL)
free(Destination);
Destination = malloc(len + 1);
memmove(*Destination, Source, len);
Destination[len] = '\0'; //null terminate
}
that way, I can call it from the main function and perform the operation this way:
char *MySource = "abcd";
char *MyDestination;
NSV_String_Copy (MySource, MyDestination);
However, it does not work as intended. please help!
C passes arguments by value, which means that you can't change the caller's MyDestination using the function prototype in the question. Here are two ways to update the caller's copy of MyDestination.
Option a) pass the address of MyDestination
void NSV_String_Copy (char *Source, char **Destination)
{
int len = strlen(Source);
if (*Destination != NULL)
free(*Destination);
*Destination = malloc(len + 1);
memmove(*Destination, Source, len);
(*Destination)[len] = '\0'; //null terminate
}
int main( void )
{
char *MySource = "abcd";
char *MyDestination = NULL;
NSV_String_Copy(MySource, &MyDestination);
printf("%s\n", MyDestination);
}
Option b) return Destination from the function, and assign it to MyDestination
char *NSV_String_Copy (char *Source, char *Destination)
{
if (Destination != NULL)
free(Destination);
int len = strlen(Source);
Destination = malloc(len + 1);
memmove(Destination, Source, len);
Destination[len] = '\0'; //null terminate
return Destination;
}
int main( void )
{
char *MySource = "abcd";
char *MyDestination = NULL;
MyDestination = NSV_String_Copy(MySource, MyDestination);
printf("%s\n", MyDestination);
}

How to pass a double pointer to a function without segmentation fault C language

I'm trying to pass a double pointer as an argument to a function and I can't see why the segmentation fault happen...
Here is the function:
void create_path_list(char *path_, char ***path) {
// Convert the path (string) into a list of directories
char *token = NULL;
int i = 0;
*path = (char **) realloc(*path, (i + 1) * sizeof(char *));
(*path)[i] = (char *) malloc(2);
strcpy((*path)[0], "/");
for(token = strtok(path_,"/"), i = 1; token != NULL; token = strtok(NULL, "/"), ++i)
{
*path = (char **) realloc(*path, (i + 1) * sizeof(char *));
(*path)[i] = (char *) malloc(sizeof(token) + 1);
strcpy((*path)[i], token);
}
}
Here is the main:
int main(){
char **path = NULL;
create_path_list("/dir1/dir2/dir3/file.txt", &path);
return 0;
}
sizeof(token)
Will give the size of token, which is a pointer. That will not allocate enough space to copy for the entire string
malloc(sizeof(token) + 1);
strcpy((*path)[i], token);
You should replace sizeof with a strlen
You are passing a string literal to you function and then try to change it with strtok(). You will have to pass a mutable string.
char str[] = "/dir1/dir2/dir3/file.txt" ;
create_path_list( str , &path);
Also I don't see how can you know how large is your allocated array if pointers. You will have to either return the size or NULL terminate the array.
Set the last element to null:
*path = (char **) realloc(*path, (i + 1) * sizeof(char *));
(*path)[i] = NULL ;
And print it outside the function
for( size_t i = 0 ; path[i] ; i++ )
{
printf("%s" , path[i] ) ;
}

passing arg 1 of `combine_string' from incompatible pointer type

I'm getting the compile error on the line "new_str = combine_string(newstr, "test");" Error: passing arg 1 of `combine_string' from incompatible pointer type
char * combine_string(char *, char *);
....
char *new_str;
new_str = newstr(item, strlen(item));
new_str = combine_string(newstr, "test");
...
char * combine_string(char *name, char *name2)
{
char *retval;
retval = erealloc(retval, (strlen(name) + strlen(name2) + 1));
if (retval != NULL)
sprintf(retval, "%s%s", name, name2);
else
free(name); //Wouldn't use it any longer
return retval;
}
...
char *newstr(char *s, int l) {
char *rv = emalloc(l + 1);
rv[l] = '\0';
strncpy(rv, s, l);
return rv;
}
The way you have it declared, newstr is a function, while new_str is a char*.
You probably meant to pass in combine_string(new_str, "test"); instead of how you have it.
I might suggest giving your variables and functions more descriptive names in the future to avoid these kinds of things!
EDIT: If you're wanting to use the return value of a call to newstr() as arg 1 of combine_string() then you will have to pass the proper parameters in to newstr() like so
new_str = combine_string(newstr(other_str, length_of_other_str), "test");
newstr is a function, apparently, not a char *
new_str = newstr(item, strlen(item));
new_str = combine_string(newstr, "test");
do you want:
new_str = combine_string(new_str, "test");
?

Resources