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!
Related
First of all, I'm sorry for my bad English.
I have a question about 'realloc' function in language C.
I thought it allocates memories with given length.
When the memories ain't enough for the given length, it copies whole memories to another memory pointer and returns it.
I wanted to use realloc function with preserving the old memories.
So I sentenced another pointer and made it pointing at the old memories.
But whenever 'realloc' function works, it frees the old memories.
How can I preserve old memories?
In addition, I want to know why this is happenend.
the below is code and its result I've used for testing realloc function.
#include <stdio.h>
#include <stdlib.h>
int* ptr1, lenPtr1;
int* ptr2;
void double_ptr1(){
lenPtr1 *= 2;
ptr1 = (int*)realloc(ptr1, sizeof(int) * lenPtr1);
}
void print(){
printf("ptr1 -> %p, *ptr1 = %d\n", ptr1, *ptr1);
printf("ptr2 -> %p, *ptr2 = %d\n", ptr2, *ptr2);
printf("\n");
}
int main(){
lenPtr1 = 10;
ptr1 = (int*)malloc(sizeof(int) * lenPtr1);
ptr2 = ptr1;
*ptr1 = 10;
print();
double_ptr1();
print();
system("pause");
return 0;
}
ptr1 -> 0108D2F0, *ptr1 = 10
ptr2 -> 0108D2F0, *ptr2 = 10
ptr1 -> 00FF5740, *ptr1 = 10
ptr2 -> 0108D2F0, *ptr2 = -17891602
An example incorporating all improvements suggested in the comments and avoiding the use of global variables, and freeing all allocated memory before the program exits. There is only a need to hold the terminal window open on windows, so conditionally enclose the system("pause");.
Putting it altogether, you would have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *double_ptr (int *ptr, int *ptrsz) /* pass needed information as parameters */
{
int *newptr = malloc (2 * *ptrsz * sizeof *newptr); /* allocate new block of mem */
if (newptr) { /* validate allocation */
memcpy (newptr, ptr, *ptrsz * sizeof *ptr); /* copy to new block of mem */
*ptrsz *= 2; /* update allocated size */
}
return newptr; /* return pointer */
}
void print (int *ptr1, int *ptr2) /* pass needed information as parameters */
{
/* only one call to printf required */
printf ("ptr1 -> %p, *ptr1 = %d\nptr2 -> %p, *ptr2 = %d\n\n",
(void*)ptr1, *ptr1, (void*)ptr2, *ptr2);
}
int main (void) {
int *ptr1 = NULL, *ptr2 = NULL, lenPtr1 = 10; /* avoid global variables */
if (!(ptr1 = malloc (lenPtr1 * sizeof *ptr1))) { /* validate EVERY allocation */
perror ("malloc-ptr");
return 1;
}
ptr2 = ptr1; /* pointer 1 and 2 hold same address where 10 is stored in memory */
*ptr1 = 10;
printf ("lenPtr1: %d\n", lenPtr1); /* output len, addresses, values */
print (ptr1, ptr2);
if (!(ptr1 = double_ptr (ptr1, &lenPtr1))) { /* double size of ptr1 */
perror ("malloc-double-ptr1");
return 1;
}
printf ("lenPtr1: %d\n", lenPtr1); /* output len, addresses, values */
print (ptr1, ptr2);
free (ptr1); /* free allcoated memory */
free (ptr2);
#if defined (_WIN32) || defined (_WIN64)
system("pause");
#endif
}
Example Use/Output
$ ./bin/doubleptrsz
lenPtr1: 10
ptr1 -> 0xb18260, *ptr1 = 10
ptr2 -> 0xb18260, *ptr2 = 10
lenPtr1: 20
ptr1 -> 0xb186a0, *ptr1 = 10
ptr2 -> 0xb18260, *ptr2 = 10
Let me know if you have further questions.
When you realloc the original pointer, which is pointed by ptr2, the address of the original pointer is removed.
So after you realloc the ptr1, ptr2 points address that does not exists anymore.
If you want to preserve old memory, then you just need to malloc(or calloc) new memory to ptr1 with no realloc original one.
When the memories ain't enough for the given length, it copies whole memories to another memory pointer and returns it.
Not quite. realloc always deallocates the old memory. It may return the same pointer.
From C11 7.20.3.4 realloc...
The realloc function deallocates the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size.... The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object)
I wanted to use realloc function with preserving the old memories.
You can't.
If you need more memory, malloc a new hunk of memory instead of reallocing the old one.
If you want to shrink memory, continue to use the memory as is. It'll work fine, it's just a waste of memory.
I'd recommend neither. Instead, redesign whatever you're doing so the pointer is accessed indirectly. Perhaps using a pointer to a pointer. Or put the pointer inside a struct and pass around a pointer to the struct.
Alternatively, redesign it so you do not need to realloc. For example, when reading from a file use a fixed size buffer to read the line and then copy that to memory with exactly enough space.
// A large buffer to reuse for each line.
char buf[BUFSIZ];
while( fgets(buf, sizeof(buf), fp) ) {
// Allocate exactly enough space for the line.
// In reality, use strdup.
char *string = malloc(strlen(buf) + 1);
strcpy(string, buf);
}
Or change to a data structure which does not rely on a single block of memory. For example, a linked list instead of an array.
In addition, I want to know why this is happened.
There are many implementations of malloc, but they all must allocate contiguous blocks of memory with no overlap.
Consider two calls to malloc.
char *foo = malloc(8);
char *bar = malloc(8);
And let's say foo and bar are allocated adjacent blocks of memory like so. (Note: there's no guarantee they will be adjacent and many reasons why they shouldn't be.)
0123456789abcdef0123456789abcdef
^^^^^^^^
| ^^^^^^^^
foo |
bar
Now you try to grow foo.
foo = realloc(foo, 16);
If realloc tries to keep the same pointer, foo would have to overlap into bar's memory.
0123456789abcdef0123456789abcdef
^^^^^^^^^^^^^^^^
| ^^^^^^^^
foo |
bar
That's not allowed, allocations cannot overlap. They also must be contiguous, so it cannot do this:
0123456789abcdef0123456789abcdef
^^^^^^^^ ^^^^^^^^
| ^^^^^^^^
foo |
bar
If it were allowed to do that, pointer math would not work. You would not be able to reliably add to foo to walk through its allocated memory.
So realloc must free foo and allocate a new block. (Again, no guarantee where it will be allocated.)
0123456789abcdef0123456789abcdef
^^^^^^^^
| ^^^^^^^^^^^^^^^^
bar |
foo
I am receiving the following error when running this code.
Error in `main': free(): invalid pointer:
My idea is to use a pointer allocated through malloc. This is a sample code.
Please let me know why I am receiving this error.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int c=10;
int* ptr = NULL;
ptr = (int*)malloc(sizeof(int));
if(ptr == NULL)
{
printf("Memory not allocated");
exit(0);
}
ptr = &c;
free(ptr);
ptr=NULL;
}
int c=10;
Variable c allocated on the stack.
ptr = (int*)malloc(sizeof(int));
Assign address of allocated memory on the heap to ptr
ptr = &c;
Assign address of c to ptr.
You have two problems in your code.
Memory Leak. You have lost address of allocated memory since you used reassign of ptr. In this case you don't have any other way to free memory allocated on the heap until program ends.
You can't free memory allocated on the stack with free() function. It's auto variables
So, If you were trying to assign the value of c to the allocated space:
*ptr = c;
Why am I receiving an invalid pointer error?
Because you free a pointer that was not allocated with malloc (or realloc).
You have a memory leak, i.e. you lose a malloced pointer with ptr = &c, which assigns the address of c to ptr, losing the value returned by malloc.
Well to do that you need to allocate for a pointer of pointer like this
#include <stdio.h>
#include <stdlib.h>
int main() {
int c=10;
int** ptr = NULL;
ptr = (int**)malloc(sizeof(int*));
if(ptr == NULL)
{
printf("Memory not allocated");
exit(0);
}
*ptr = &c;
free(ptr);
ptr=NULL;
}
the problem in your case that you are freeing a non dynamic allocated memory and that gives you an error, and even in other cases you should always keep the address of the allocated memory to free it when you no more need it for example
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr1 = (int*)malloc(sizeof(int));
int *ptr2 = (int*)malloc(sizeof(int));
*ptr1 = 5;
*ptr2 = 10;
// this is wrong because now there is no way to free
// the address of the allocated memory to ptr1
ptr1 = ptr2;
free(ptr1);
// this gives an error because ptr2 is already free
free(ptr2);
}
Conclusion:
If you want to allocate to store a pointer, then you need to allocate for a pointer to pointer, so the pointer of the allocated memory stay so you can free that memory when you no longer need it
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;
}
I have this code snippet to understand the memory management function void free(void*) in C. What I know about free function is that it will deallocate the memory that is managed by a pointer. I want to see what will happen after a block of memory is set free and whether the pointer associated is still accessible to that block of memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_SIZE 20
int main(int argc, char *argv[])
{
char originalChar [] = "123456789";
char *myChar = (char*) malloc(sizeof(char) * STR_SIZE);
if (!myChar) {
printf("allocation failed!");
exit(1);
}
char *isOk = strncpy(myChar, originalChar, STR_SIZE*sizeof(char));
if(!isOk) exit(1);
char *myCharCopy = myChar;
printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
printf("The strings = %s\n", myChar);
printf("The strings = %s\n", myCharCopy);
free(myChar);
printf("----- free happened here -----\n");
// myChar = NULL;
printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
printf("The strings = %s\n", myChar);
printf("The strings = %s\n", myCharCopy);
return 0;
}
Then, I got those results from its output.
oC = 1482066590, mCC = 826278544; mC = 826278544
The strings = 123456789
The strings = 123456789
----- free happened here -----
oC = 1482066590, mCC = 826278544; mC = 826278544
The strings = 123456789
The strings = 123456789
This result makes very little sense to me. Because free function is supposed to set free the block of memory but it is NOT from the result. What on earth happened here? Besides, it seems the pointer associated with the memory on heap is still accessible to that freed memory. Why this will happen since it is freed?
As per the C11 standard, chapter §7.22.3.3, The free function
The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation.[..]
It does not mandate that the pointer would be set to NULL (or anything else, for that matter). free()-ing is just an indication to the OS that the allocated memory can be reclaimed and reissued, as and when required.
Accessing free()-d memory is undefined behavior. So, once free() is called, you should not be accessing the pointer anymore.
For this very reason, it is often considered a good practice to set the free()-d pointer to NULL immediately after the call to free() so that to avoid any unintended access to already freed memory.
That said,
printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
also invokes undefined behavior. %d is to print an int, not a pointer (or string, for that matter). In case you want to print the address, you may want to use
printf("oC = %p, mCC = %p; mC = %p\n", (void*)originalChar, (void*)myCharCopy, (void*)myChar);
Per the C standard:
7.22.3.3 The free function
...
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.
But now your code accesses the memory, which invokes undefined behavior, per the C Standard again:
J.2 Undefined behavior
1 The behavior is undefined in the following circumstances:
...
The value of a pointer that refers to space deallocated by a call to
the free or realloc function is used (7.22.3).
Including appearing to "work".
There are some related discussions about my problem but there are no clearly explanations about my problem.
I thought that I must free() whatever I malloc(), no matter when or where but I have to do it, to prevent a memory leak.
So i have the following program:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int *ptr;
ptr = malloc(256);
if (ptr == NULL) {
printf("Out of memory\n");
return 1;
}
*ptr = 10;
printf("The value of PTR is:\t%d\n",*ptr);
free(ptr);
return 0;
}
I have a pointer and I dynamically allocated some memory (256), then I checked for NULL letter I free() it.
Until here everything is OK: to the pointer was dynamically allocated some memory and then I free() it.
Now i will use a char pointer this time and after i will dynamically allocated some memory (256), i will point that pointer to a string literal, lets say MICHI:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
char *ptr;
ptr = malloc(256);
if (ptr == NULL) {
printf("Out of memory\n");
return 1;
}
ptr = "michi";
printf("%s",ptr);
free(ptr);
return 0;
}
Here I am doing something wrong because if i try to free() it, well it will not work because it happens that i'm going to free a non-heap object.
So i'm lost in here, because i thought that everything you malloc() you have to free() it.
What exactly make that pointer, after points to a string literal, to not need to be free()ed
ptr = malloc(256);
...
ptr = "michi";
printf("%s",ptr);
free(ptr);
As you allocate memory to ptr and then you make it point to string literal. Thus pointer ptr no longer points to memory allocated by malloc.
And to free memory not allocated by malloc or similar functions cause error in program.
Do this instead:
strcpy(ptr,"michi");
In the first program you allocated memory
ptr = malloc(256);
and initialized its first sizeof( int ) bytes with integer value 10.
*ptr = 10;
The pointer itself was not changed. So in this statement
free(ptr);
pointer ptr points to the memory that was allocated using malloc.
In the second program you allocated memory the same way as in the first program
ptr = malloc(256);
But then you reassigned the pointer itself with the address of the first character of string literal "michi"
ptr = "michi";
Compare the left sides of this assignment
*ptr = 10;
and of this assignment
ptr = "michi";
As you see they are different. In the first case you are changing the allocated memory while in the second case you are changing the pointer itself.
Thus in this statement
free(ptr);
pointer ptr does not point to the memory that was previously allocated. It points to the memory occupied by the string literal that was not allocated using malloc.
Thus this statement is wrong and the program has a memory leak because the previous memory that was allocated using malloc was not freed,
Because constant literals are stored in a way for the lifetime of the program, in a read-only region of memory in most of the platforms.
When you use free you are trying to free the memory allocated, not the pointer itself, that's why it's not gonna work if you try to do that in a read-only region of memory
When you reassign your pointer you're losing track of the allocated memory and therefore creating a memory leak.
The memory leak is created because you first allocated the memory and assign it to your pointer, when you've a pointer pointing to it you can easily free that memory, but when you don't have any more reference to that memory you can't.
That's what's happening, when assign the literal to the pointer there's no more reference to that address, it was allocated but it's not reachable anymore, in this way you can't free the memory.
The problem is that you have lost the pointer the second you assigned another value to it:
ptr = malloc(256);
if (ptr == NULL) {
printf("Out of memory\n");
return 1;
}
// here you should free your memory
ptr = "michi";
printf("%s",ptr);
// this fails, because ptr now points to the const static string "michi" you have coded yourself. The assignment didn't copy it, just changed what ptr points to.
free(ptr);
Try this.
#include <stdio.h>
int main(void)
{
char *str:
str = (char*)malloc(sizeof(str) * 4);
printf("Addr of str before: %p\n", str);
str = "Joe";
printf("Addr of str after: %p\n",str);
return(0);
}
/* you will get the following addresses:
Addr of str before: 0x51fc040
Addr of str after: 0x4006f0
this is becuase you changed where str points to. 0x51fc040 is memory allocated using malloc and 0x4006f0 is the memory Adress of the string literal "Joe".
I would advice the following...*/
#include <stdio.h>
int main(void)
{
char *str;
str = (char*)malloc(sizeof(str) * 4);
printf("Addr of str before: %p\n", str);
str =strncpy(str, "Joe", 4);
printf("Addr of str after: %p\n",str);
free(str);
return (0);
}
/* you will get the following addresses:
Addr of str before: 0x51fc040
Addr of str after: 0x51fc040
This is because strncpy copies the string literal to the memory dynamically allocated. and it is safer than stcpy, since it prevents buffer overflow