Function to free pointers not working - c

I'm learning C and trying to figure out an elegant way to free my pointers at the end of the execution.
After hours debugging and experimenting different things with the following code, I couldn't manage to figure out what I was doing wrong:
int ClosePointers(char *pointersToClose[], int arraySize) {
int index;
for(index = 0; index < arraySize; index++) {
char *pointer = pointersToClose[index];
free(pointer);
}
return (0);
}
int main(int argc, char *argv[]) {
char *pointersToClose[4];
char *pointer1;
char *pointer2;
char *pointer3;
char *pointer4;
pointersToClose[0] = pointer1;
pointersToClose[1] = pointer2;
pointersToClose[2] = pointer3;
pointersToClose[3] = pointer4;
pointer1 = malloc(10);
pointer2 = malloc(10);
pointer3 = malloc(10);
pointer4 = malloc(10);
/*some important code here using the pointers*/
ClosePointers(pointersToClose, 4);
return 0;
}
I'm getting the following error:
* glibc detected * /home/workspace/Debug/Test-POC: free(): invalid pointer: 0x00000038ce7b9850 ***
Could you help me out pointing what I'm doing wrong?

You're calling free on those pointers, but you never allocate any memory to them with malloc. In fact, the pointers you are trying to free are uninitialized, so they could contain anything.
When you set the values of pointersToClose, you're assigning the current value of pointer1, pointer2, etc., not whatever value they may contain when "some important code here using the pointers" runs.
Passing a pointer value to free that was not returned by malloc/realloc/calloc results in undefined behavior.
If you want to do this, try putting the address of each of the pointers in question in your array.
int ClosePointers(char **pointersToClose[], int arraySize) {
int index;
for(index = 0; index < arraySize; index++) {
char **pointer = pointersToClose[index];
free(*pointer);
}
return (0);
}
int main(int argc, char *argv[]) {
char **pointersToClose[4];
char *pointer1;
char *pointer2;
char *pointer3;
char *pointer4;
pointersToClose[0] = &pointer1;
pointersToClose[1] = &pointer2;
pointersToClose[2] = &pointer3;
pointersToClose[3] = &pointer4;
/*some important code here using the pointers*/
ClosePointers(pointersToClose, 4);
return 0;
}

Could you help me out pointing what I'm doing wrong?
You should use free() only on pointers that you allocated on the heap using the malloc() function.
What happens, is that within the heap (a reserved memory space), the length you gave as parameter to the malloc() function is allocated for your use, and it returns the address to the first word of that memory space so it can be assigned to a pointer.
When you use free(), it's deallocating that memory space so it can be reused.
Here, you create pointers variables that points to nothing (actually they point to a random value). So what's happening when you call free() on those variables is that you try to deallocate some random memory space that is not within the managed space, called the heap. As those addresses are unlikely to be allocated by malloc(), the free() function cannot know what to do with it, and therefore will return an error!
Read on about what are the stack and the heap to better understand what those are. Also, read the C programming language book by Kernighan and Ritchie where it's all well explained.

In your code. pointer1 is unitialized. It points to invalid memory. Passing that to free() invokes undefined behavior.
Quoting C11, chapter §7.22.3.3, (emphasis mine)
The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if
the argument does not match a pointer earlier returned by a memory management
function, or if the space has been deallocated by a call to free or realloc, the
behavior is undefined.
You need to either
set that to NULL (null-pointer constant)
use malloc() or family to allocate free-able memory first.
That said, pointer2, pointer3 and pointer4 are undeclared in your code but probably that's a typo, so we can overlook it.

In order to free a pointer you must first have allocate memmory for it. You are going to free pointers that are never allocated. Try the following code to understnd what you did wrong
int AllocatePointers(char *pointersToClose[], int arraySize) {
int index;
for(index = 0; index < arraySize; index++) {
pointersToClose[index] = malloc(50*sizeof(char));
}
return (0);
}
int main(int argc, char *argv[]) {
char *pointersToClose[4];
char *pointer1;
char *pointer2;
char *pointer3;
char *pointer4;
pointersToClose[0] = pointer1;
pointersToClose[1] = pointer2;
pointersToClose[2] = pointer3;
pointersToClose[3] = pointer4;
AllocatePointers(pointersToClose, 4);
/*some important code here using the pointers*/
ClosePointers(pointersToClose, 4);
return 0;
}

Related

How does free() works in this case? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Let's say a function allocates memory for a string and returns it.
The variable, that calls that function, in which is stored its return string is an array of pointers to char already dynamically allocated.
My doubt is, when I'll free the variable's memory, is it going to free both the variable memory and the in-function string memory or does the in-function allocated memory became one with the variable one?
char *function() {
//allocates memory for <string>
return <string>
}
int main() {
//<variable> declaration
//<variable> allocation
<variable> = function();
free(<variable>);
return 0;
}
For practical reasons I omitted the //function declaration part
Thanks for your attention and help!
There are two possible cases:
Function allocates memory using dynamic memory allocation and it is 100% correct
char *func(void)
{
char *x = malloc(100);
/* some code */
return x;
}
void foo(void)
{
char *y = func();
free(y);
}
Other ways of allocating memory. All invoke the undefined behavior when you try to free them. Additionally there is an another UB when pointer to automatic variable is used outside the scope it was defined in.
char w[100];
char *func(void)
{
char x[100];
/* some code */
return x;
}
char *func1(void)
{
static char x[100];
/* some code */
return x;
}
char *func2(void)
{
return w;
}
void foo(void)
{
char *y = func();
y[0] = 'a'; //UB
free(y); //UB
y = func1();
y[0] = 'a';
free(y); //UB
y = func2();
y[0] = 'a';
free(y); //UB
}
I posted a complete example of it here: https://stackoverflow.com/a/63756135/11234199
My doubt is, when I'll free the variable's memory, is it going to free both the variable memory and the in-function string memory or does the in-function allocated memory became one with the variable one?
Please run the program provided there since it will do just this: create and destroy a block of pointers to char, just like argc/argv block that every main() function gets for free in C
The program I posted there shows how to build dynamically a block of strings and how to consume it, allocating memory in blocks and trimming it at the end for the exact used size
But here I will provide a 20-line example that builds an array of pointer the same way
Your function
char *function()
{
//allocates memory for <string>
return <string>
}
returns just one pointer to a char. You could write
char one_char = *function();
and it is just what is is. There is not string in C in fact. And if function is char* then *function is char.
Inside the function you can malloc() a block and return the address in the function, with a convenient '\0' at the start of a 1MB block and it would be fine.
For this thing to work we need to build it carefully
Fact is that in general we want something like
typedef struct
{
int argc;
char** argv;
} stringArray;
just like the familiar main() prototype.
And why is that?
Well, we want an array of pointers to char due to the conveniente of iterate through hem just like an ordinary array like argv[0], argv[1]...
But it is essential the argc thing. As in
char** argv;
we have no way to know how many pointers are in the area pointed by *argv.
we just know that
argv is char**
*argv is char*, a pointer to char
**argv is a char, a single char
we have to build the block the way we need, or just hope that someone gently did that before we use.
If there are one hundred strings at *argv it is because someone allocated 100 pointers to char and put the address in argv. And after that allocated 100 strings of who knows what size, using the one hundred pointers. And then made sure the strings are all null-terminated.
This is how it works.
The code below builds an example 10-string block, and just for fun the strings are build the way we see here:
we got 10 strings:
'0' [len: 1]
'01' [len: 2]
'012' [len: 3]
'0123' [len: 4]
'01234' [len: 5]
'012345' [len: 6]
'0123456' [len: 7]
'01234567' [len: 8]
'012345678' [len: 9]
'0123456789' [len: 10]
End of list
And back in main() the the full block is destroyed from inside out.
here is the code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int argc;
char** argv;
} stringArray;
stringArray* get_the_block(void);
int main(void)
{
stringArray* string_array = get_the_block();
printf("we got %d strings:\n\n", string_array->argc);
char** array = string_array->argv; // just for readability
for (int i = 0; i < string_array->argc; i += 1)
printf("'%s' [len: %zd]\n", array[i], strlen(array[i]));
printf("\nEnd of list\n");
// free() the block
// since string_array is also a pointer we have 3 levels
// 1st free() the strings
for (int i = 0; i < string_array->argc; i += 1)
free(array[i]);
// 2nd free() the block of pointers
free(string_array->argv);
// 3rd free() the control structure
free(string_array);
return 0;
}; // main()
stringArray* get_the_block(void)
{
// this is an useless example
// it builds a 10-string block and
// return it
const char* text = { "0123456789" };
// building the block of strings
// "0", "01", "012" ... "123456789"
char** string = (char**)malloc(10 * sizeof(char*));
for (int i = 0; i < 10; i += 1)
{
string[i] = malloc((1 + 1 + i) * sizeof(char));
memcpy(string[i], text, 1 + i);
string[i][i + 1] = 0; // strings are null-terminated
};
// builds the struct to return, just like the system
// does for main()
stringArray* block = (stringArray*)malloc(sizeof(stringArray));
block->argc = 10;
block->argv = string;
return block;
};
The variable, that calls that function, in which is stored its return
string is an array of pointers to char already dynamically allocated.
It means that the returned pointer from the function can be assigned only to one element of the dynamically allocated array.
For example
char **s = malloc( 10 * sizeof( char * ) );
s[0] = function();
So you may free the memory allocated in the function and the pointer to which was assigned to the element s[0] like
free( s[0] );
After that you may for example reassign the pointer with an address of other dynamically allocated string.
But this call will not free the memory allocated for the whole array of pointers s. To free it you have to write
free( s );

free() : invalid pointer and how to reuse a currently freed pointer

I want to address my pointer to another object and free the memory of previous object. This is what I did but I had a invalid pointer error. What is the right way to do it?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
int number = 5;
int number2 = 10;
// Give memory manually
int *pointer2number = (int *) malloc(sizeof(int));
pointer2number = &number;
printf("Number is %i\n", number);
printf("Address of number is %p\n", pointer2number);
// Free memory
free(pointer2number);
pointer2number = (int *) malloc(sizeof(int));
pointer2number = &number2;
printf("New number is %i\n", *pointer2number);
return 0;
}
int *pointer2number = (int *) malloc(sizeof(int));
pointer2number = &number;
You assign the address of number to the pointer pointer2number and with that replace the address of the allocated dynamic memory stored in pointer2number before.
The same goes for the second attempt with number2.
Any attempt to free() a memory not previously allocated by a memory-management function, invokes undefined behavior:
"The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined."
Source: ISO/IEC 9899:2018 (C18), Section 7.22.3.3/2
And as side-effect, the previously allocated dynamic memory isn´t free()d with that too.
Overthink the logic of your program!

Using pointers to make a new string in function

I am doing a bit of studying about C pointers and how to transfer them to functions, so I made this program
#include <stdio.h>
char* my_copy(pnt);
void main()
{
int i;
char a[30];
char* p,*pnt;
printf("Please enter a string\n");
gets(a);
pnt = a;
p = my_copy(pnt);
for (i = 0; i < 2; i++)
printf("%c", p[i]);
}
char* my_copy(char* pnt)
{
char b[3];
char* g;
g = pnt;
b[0] = *pnt;
for (; *pnt != 0; pnt++);
pnt--;
b[1] = *pnt;
b[2] = NULL;
return b;
}
It's supposed to take a string using only pointers and send a pointer of the string to the function my_copy and return a pointer to a new string which contains the first and the last letter of the new string. Now the problem is that the p value does receive the 2 letters but I can't seem to print them. Does anyone have an idea why?
I see five issues with your code:
char* my_copy(pnt); is wrong. A function prototype specifies the types of the parameters, not their names. It should be char *my_copy(char *).
void main() is wrong. main should return int (and a parameterless function is specified as (void) in C): int main(void).
gets(a); is wrong. Any use of gets is a bug (buffer overflow) and gets itself has been removed from the standard library. Use fgets instead.
b[2] = NULL; is a type error. NULL is a pointer, but b[2] is a char. You want b[2] = '\0'; instead.
my_copy returns the address of a local variable (b). By the time the function returns, the variable is gone and the pointer is invalid. To fix this, you can have the caller specify another pointer (which tells my_copy where to store the result, like strcpy or fgets). You can also make the function return dynamically allocated memory, which the caller then has to free after it is done using it (like fopen / fclose).
You're returning an array from my_copy that you declared within the function. This was allocated on the stack and so is invalid when the function returns.
You need to allocate the new string on the heap:
#include <stdlib.h>
b = malloc(3);
if (b) {
/* Do your funny copy here */
}
Don't forget to free() the returned string when you've finished with it.

strcpy and strcat in Keil C compiler

I used this code to print some string,but it does not print any thing.What is the problem?
char* getNotFilledEncryptionParams(void)
{
char* nofilledStr;
char tmp[3];
const char * arr[]= {" P,"," Q,"," A,"," B,"," C,"," R,"," S0,","S1,","S2,","F1,","G1"};
for(i=0;i<11;i++)
{
if(filledParams[i] == 0)
{
strcpy(tmp,arr[i]);
strcat(nofilledStr,tmp);
}
}
return nofilledStr;
}
Usage:
int main(void){
char *remaining;
remaining = getNotFilledEncryptionParams();
printf("\r\n Remaining item:%s",remaining);
}
I think the problem is in const char * arr[] and I changed it,but the problem remains.
You didn't allocate any memory for noFilledStr, so its value is indeterminate and strcat(noFilledStr, tmp) is undefined.
Use malloc to allocate memory and initialize noFilledStr with the returned pointer:
char* noFilledStr = malloc(number_of_bytes);
The strings in arr are char[4], not char[3] (do not forget the null byte!). tmp is too small to hold them, so strcpy(tmp, arr[i]) writes out of bounds.
You are trying to build the string to return in the location pointed to by nofilledStr but this pointer is pointing somewhere as you do not initialize it. You could use a sufficiently large static char[] array if you do not have to deal with multiple threads. Otherwise, use malloc() and require the caller to free() the returned string when he is done with it.

Buffer Overflow issue in environment variable replacement scheme

Whenever the environment variable's value is larger than its key in this method, I get a buffer overflow. Target is part of a dynamically allocated two dimensional array for tokens. Whenever I replace the token that's an environment variable with a value longer than it, it flows into the next token. I've tried adding a realloc to try and fix it, but it doesn't work or leads to a segfault.
If anyone has any suggestions or can point me at something I"m overlooking, I'd greatly appreciate it, because I have a feeling I'll be kicking myself when I find it out anyway.
The method is:
void envReplace(ENV *evlist, char *Target)
{
if (Target[0] == '#')
{
memmove(Target, Target+1, strlen(Target));
for(q = 0; q<16; q++)
{
if(evlist[q].envVariable!=NULL)
{
if(strcmp(Target, evlist[q].envVariable)==0)
{
//this is where I'd add the realloc as realloc(Target, strlen(evlist[q].Value))
strcpy(Target, evlist[q].Value);
return;
}
}
}
printf("Variable not found\n");
}
else
{
printf("A value that didn't start with # was an argument\n");
return;
}
}
The data structure ENV is:
typedef struct envStorage
{
char *envVariable;
char *Value;
}ENV;
You can pass a pointer to a pointer, like this, and then you can call realloc() inside the function, modifying the original pointer.
void func (char **to_change) {
// Changes the char *target in main()
*to_change = (char *) realloc(*to_change, 20);
sprintf (*to_change, "Blablablablabla\n");
}
int main (int argc, char **argv) {
char *target = (char *) malloc (10);
func(&target);
printf(target);
free(target);
}
In this example, func() writes to the original pointer char *target in the main() function.
What happens in your code, is that you realloc() and assign to a copy of the pointer. The pointer is copied when you call envReplace(). When this function returns, the original pointer contains the old memory address, which is no longer valid allocated memory (it was freed by realloc()).

Resources