I trying to use memcpy to copy content from one array to another, the code is as follow:
#include <stdio.h>
int main(){
int *a;
a = (int*) malloc(sizeof(int) * 4);
a[0] = 4;
a[1] = 3;
a[2] = 2;
a[3] = 1;
int *b;
b = (int*) malloc(sizeof(int) * 4);
memcpy(&b, &a, sizeof(a));
free(a);
for (int i = 0; i < 4; i++){
printf("b[%d]:%d",i,b[i]);
}
printf("%d\n",sizeof(b));
free(b);
return 0;
}
However, when I try to run it, I encounter the following error:
b[0]:4b[1]:3b[2]:2b[3]:18
mem(6131,0x7fffbb4723c0) malloc: *** error for object 0x7fa5a4c02890: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
This error disappear if I remove the free(b) piece of code, however, I don't know why since I explicitly allocate resource to it.
Your memcpy is wrong. You're copying the value of the pointer a into b instead of copying the data pointed by a into the buffer pointed by b. You end up doing a double free because a and b point to the same place. Replace your memcpy call with this:
memcpy(b, a, sizeof(int)*4);
memcpy(&b, &a, sizeof(a));
This doesn't copy the 4 ints that a points at to the 4 ints that b points at.
This instead overwrites b with the contents of a. Then you end up doing a double free, since both a and b contain the same address.
I'll repeat my comment on your question: You need to take the time to appreciate the difference between a pointer and a pointee. What holds and address, and what is at that address.
This is the exact problem why we say not to cast the return value of malloc() and family in C..
First things first, you are missing stdlib.h include and because of that, the prototype of malloc() is not known and your compiler assumnes that it returns an int. This creates the mismatch between the implicit declaration and the actual definition, which at a later stage, invokes undefined behavior.
That said, another major issue is when you write memcpy(&b, &a, sizeof(a)); which is very wrong. You want to supply a and b themselves, as you want to copy the contents of the memory location pointed by a to the memory location pointed by b, not the address of the pointers.
In your case, the erroneous call actually messes up the contents of b, i.e., the actual pointer returned by malloc(). Therefore, as we know, passing a pointer which was not exactly returned by memory allocator functions or already free()-d, to free() causes UB, quoting C11, chapter §7.22.3.3,
[...] 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're getting into trouble, as the current pointer held by b is the same one as a which has been already passed to free(). As mentioned in the other answer(s) [1][2], you need to write
memcpy(b, a, sizeof(int)*4);
Moral of the story: Enable compiler warnings and always check the data types.
Maybe because you free b when you do free(a). Because the memory zone is the same after doing memcpy. Try to do free(b) at the end, without the free(a).
Related
For example:
void heaptest(){
int *a;
a=(int*)malloc(1024*4);
int i=1024;
while(i--){
*a=i;
//printf("%d",*a);
a++;
}
free(a);
}
When the 'a' was used as a pointer, assume it points to address "0x20000". And the scope of this heap area is from 0x20000 to 0x21000. totally 4096 bytes.
after the while loop, the 'a' was pointed to 0x21004, which is actually out of the scope of the defined heap. if we free the heap using
free(a)
Will this heap be freed successfully?
For my observation, when I use this func in Visual Studio. it will show
Invalid address specified to RtlValidateHeap
and the value of a is 0x21004 before the free() operation whenever whether there is a printf() function in the while loop.
When I use this function on Keil-MDK for STM32F7(Cortex M7), it shows nothing but before the free operation. the value of 'a' will become 0x00000;
But when I add the printf() function shown in the code. the value of 'a' will back to the initial value 0x20000.
So, the final question is, could we change the value of the heap pointer? or assign it back to the initial value every time before the free() operation?
Will this heap be freed successfully?
It is impossible to say. You invoke undefined behavior by passing a pointer value to free() that was not returned by malloc() or one of the other allocation functions. That could turn out to manifest as freeing the block into which the pointer points, but more likely it produces an error, or worse: silent memory corruption.
Note in particular that it is the pointer value that matters. The variable, if any, in which you store the pointer value has nothing directly to do with it.
could we change the value of the heap pointer?
In the sense that the pointer is a value, no, you can no more change it than you can change the value 1. But you can cause a variable in which that value is stored to instead contain a different value. You may even be able to do so in a way that allows you to recover the original value, so as to retain the ability to free the allocated memory.
You need to free the address your were given. What you do to the code's variables in between does not matter.
This is valid:
char * p = malloc(42);
p++;
p--;
free(p);
This as well:
char * p = malloc(42);
char * q = p:
/* p += 43; */ /* Invokes UB, as making q point more then just one past the object. */
q += 42; /* Just one past the allocated memory. */
q -= 42;
free(q);
This isn't
char * p = malloc(42);
p++;
free(p);
This neither:
char * p = malloc(42);
p--;
free(p);
An address passed to free must have been obtained as the return value of malloc/calloc/etc. Passing any other pointer invokes undefined behavior.
From the MSDN page for free:
The free function deallocates a memory block (memblock) that was
previously allocated by a call to calloc, malloc, or realloc. The
number of freed bytes is equivalent to the number of bytes requested
when the block was allocated (or reallocated, in the case of realloc).
If memblock is NULL, the pointer is ignored and free immediately
returns. Attempting to free an invalid pointer (a pointer to a memory
block that was not allocated by calloc, malloc, or realloc) may affect
subsequent allocation requests and cause errors.
Keep track of the original pointer so you can later pass it to free:
void heaptest(){
int *a, a_sav;
a=(int*)malloc(1024*4);
a_sav = a; // save the original pointer
int i=1024;
while(i--){
*a=i;
printf("%d",*a);
a++;
}
free(a_sav); // free the saved pointer
}
Calling free with an argument that does not point to an adress allocated via malloc, calloc or realloc is undefined behavior. You have absolutely zero information on what it will do. Try something in this form.
void heaptest(){
// Declare a const to make sure we free the right adress in the end
int * const a = (int*)malloc(1024*size_of(int));
int i=1024;
do {
// This will loop from a[0] to a[1024] which is what I assume you meant to do
a[1024-i] = i;
} while (--i);
free(a);
}
It's hard to say if this program does what you wanted. You can change i or the index or the right hand side of the assignment to suit your needs but don't do the loop like you did because it's way more error-prone.
Thanks for notice my question.
In C Primer Plus, it first writes
The argument to free() should be a pointer to a block of memory allocated by malloc(); you can’t use free() to free memory allocated by other means
which means ONE malloc(), ONE and ONLY one free().
But later it goes
It’s okay to use a different pointer variable with free() than with malloc(); what must agree are the addresses stored in the pointers.
which seems contradict to the first statement.
So my understanding is that as long as a pair of malloc() and free() share the same address there is no error, and the name of pointers doesn't matter. Am I right?
For example:
void* p = malloc (100);
void* q = p;
free (q);
...is fine. The argument for free () is the value that was returned by malloc. The sentence
"It’s okay to use a different pointer variable with free() than with
malloc()"
is actually pointless and just creates confusion - of course it is fine to use different variables as long as the value is the same.
Just remember that freeing any alias, makes all the pointers invalid
int *a, *b, *c, *d, *e;
a = malloc(42 * sizeof (int));
b = a;
c = b;
d = c;
e = d;
a[0] = 42;
b[1] = 100; // same as a[1]
c[2] = 999; // same as a[2]
d[3] = -1; // same as a[3]
e[4] = 0; // same as a[4]
free(d); // for example
// all of a, b, c, d, and e are now invalid;
Variables contain some value, which could be a pointer (i.e. a memory address).
Two variables could contain the same pointer (that is, the same address), it is called pointer aliasing.
What matters to free is to get the value of a pointer previously given by malloc (that is a memory address previously given by malloc)
I have two pointers:
1.
double *a, *b;
a = (double *) malloc (N*sizeof (double));
b = (double *) malloc (N*sizeof (double));
that point to huge memory space that I allocate using malloc. and assign values.
then if I do,
a=b;
a points to array b was pointing to.
What happens to memory allocated to a? Is following better alternative:
free(a);
a=b;
free(b);
or only
a=b;
free(b);
or a=b;
free(a);
or is it illegal?
Is it different if a is global and b is local?
In your example a=b creates a memory leak. Block of memory previously pointed to by a becomes impossible to free, because your program no longer has a pointer to it. This may not lead to an immediate problem, but over time your program runs out of memory, and mallocs start returning NULL.
Calling free(a) prior to reassignment fixes this problem. Once you assign a=b, you need to be careful with using a after calling free(b), because a becomes a dangling pointer.
Is it different if a is global and b is local?
Scope of the pointer does not matter here. The pointer has to be considered independently of the block of memory to which the pointer is pointing. The block is allocated in dynamic memory; the pointer to the block could be anywhere - static, automatic, or dynamic.
What you're doing causes the memory that you allocated for a to be leaked. That means you loose the information where it is stored in memory because you overwrite the pointer with b. If you want to assign the pointers like you do, the solution you yourself proposed
free(a);
a=b;
free(b);
would work. But keep in mind that after freeing b, a points to an invalid location, because you free'd the memory. So accessing a[0] will crash the program.
When you do a=b, a points to the array being pointed to by b. Then, the only memory you would want to free is the array initially pointed to by a. For doing that,
free(a);
a=b;
Here, you are freeing the memory being pointer to by a and making a point to the memory being pointed to by b. If you first do a=b, you have a pointing to the array pointed to by b, but are left with no way to access the memory that was earlier being pointed to by a. So, you should free a first. Moreover, if you free b later, all you would be left is with a and b both pointing to NULL.
Pointers are a really tricky thing in C. For a lot of people is hard to understand it, so for a good understanding I wrote following code:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int *p; // pointer -> will be dynamic allocated
int *a; // array -> will be dynamic allocated
// print before allocate memory (1)
printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
printf("&a: %p\ta: %p\t*a: %d\n", &a, a, *a);
printf("\n");
// allocate memory (2)
p = (int *)malloc(sizeof(int));
a = (int *)malloc(sizeof(int) * 10);
// print after allocate, but before give a value to poinetrs (3)
printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
printf("&a: %p\ta: %p\t*a: %d\n", &a, a, *a);
printf("\n");
// give a value to poinetrs (4)
*p = 1;
for (int i = 0; i < 10; i++) { a[i] = i; }
// print after we gave a value to pointers (5)
printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
printf("&a: %p\ta: %p\t*a: ", &a, a);
// because a is an array we must use a loop for print
for (int i = 0; i < 10; i++) { printf("%d ", a[i]); }
printf("\n");
printf("\n");
// free pointers (6)
free(p);
free(a);
// print pointers after free (7)
printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
printf("&a: %p\ta: %p\t*a: ", &a, a);
// because a is an array we must use a loop for print
for (int i = 0; i < 10; i++) { printf("%d ", a[i]); }
printf("\n");
printf("\n");
// try to change values after free (8)
*p = 12;
for (int i = 0; i < 10; i++) { a[i] = 3; }
// print after (8)
printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
printf("&a: %p\ta: %p\t*a: ", &a, a);
// because a is an array we must use a loop for print
for (int i = 0; i < 10; i++) { printf("%d ", a[i]); }
printf("\n");
printf("\n");
return 0;
}
Output:
&p: 0xbfe5db64 p: 0xbfe5dc24 *p: -1075452506
&a: 0xbfe5db68 a: 0xbfe5dc2c *a: -1075452502
&p: 0xbfe5db64 p: 0x8716008 *p: 0
&a: 0xbfe5db68 a: 0x8716018 *a: 0
&p: 0xbfe5db64 p: 0x8716008 *p: 1
&a: 0xbfe5db68 a: 0x8716018 *a: 0 1 2 3 4 5 6 7 8 9
&p: 0xbfe5db64 p: 0x8716008 *p: 0
&a: 0xbfe5db68 a: 0x8716018 *a: 0 1 2 3 4 5 6 7 8 9
&p: 0xbfe5db64 p: 0x8716008 *p: 12
&a: 0xbfe5db68 a: 0x8716018 *a: 3 3 3 3 3 3 3 3 3 3
Now, questions and observations:
When I print pointers before give memory for it, why pointer have a random value and a random address to point to it and why it isn't NULL?
After we use malloc, we can see the address where pointer points to changed and its value is NULL, so what malloc really does?
After we give a value to it and print it, we free it and print it again, but values and address are same as behind for array, but not for the integer, why? So what free really does?
After we freed space, we can continue to change values of array and integer, why is this possible after free space? We don't need to reuse malloc?
Because the language specification says so. The value of the pointer (i.e. the address it points to) is indeterminate. It can point anywhere, just like an int could hold any value. Reading those values, (as you do with *p and *a in the first printfs) is actually undefined behaviour.
If you mean the data it points to is 0, that is by chance. The memory allocated does not have to be zeroed out. For example, it could be part of a block previously allocated with malloc and then freed (free doesn't zero out the memory, see point 3. below.)
That is also by chance. When you free the memory, it is not zeroed out, and it does not have to be used immediately. It can keep storing old values until it is used for something else (for instance, by another allocation)
That is also undefined behaviour. You are writing to memory you no longer own. Anything can happen. The program could have crashed. By chance, it seems like you can successfully write to the array, probable because the memory is still not used by anything else that would cause a more apparent run time error.
1.When I print pointers before give memory for it, why pointer have a random value and a random address to point to it and why it isn't NULL?
You didn't make the pointer NULL. you are just declaring it. After declaring the pointer, it may have any value.
To make NULL-
int *p = NULL;
int *a = NULL;
2.After we use malloc, we can see the address where pointer points to changed and its value is NULL, so what malloc really does?
Man Page says-
void *malloc(size_t size);
The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
If your allocated memory have 0 means that is by a chance only! The memory allocated by malloc doesn't freed out. But calloc does!
3.After we give a value to it and print it, we free it and print it again, but values and address are same as behind for array, but not for the integer, why? So what free really does?
free does not mean that it will actually delete the memory! It will inform to the OS that I don't want this memory any more, use it for some other process!
You can certainly continue to use memory a after calling free(...) and nothing will stop you. However the results will be completely undefined and unpredictable. It works by luck only. This is a common programming error called "use after free" which works in many programs for literally years without "problems" -- until it causes a problem.
4.After we freed space, we can continue to change values of array and integer, why is this possible after free space? We don't need to reuse malloc?
This is totally Undefined behavior! After freeing the memory also the pointer still points to the same memory location. It is called Dangling Pointer.
To avoid dangling pointer, Make pointer to null after free!
But after freeing the memory, you need to use memory means use malloc to allocate memory and use it!
What are pointers
Pointer declarations look much like other declarations: but don't be misled. When pointers are declared, the keyword at the beginning declares the type of variable that the pointer will point to. The pointer itself is not of that type, it is of type pointer to that type. A given pointer only points to one particular type, not to all possible types. In practice, all pointers are treated as integers, but the compiler will most likely complain about an assignment between incompatible types.
int *p;
The pointer p hasn't been assigned an address, so it still contains whatever random value was in the memory it occupies (whatever value was there before it was used for p). So, provided that a pointer holds the address of something, the notation *p is equivalent to giving the name of the something directly. What benefit do we get from all this? Well, straight away it gets round the call-by-value restriction of functions. Imagine a function that has to return, say, two integers representing a month and a day within that month.
Summary
Arrays always index from zero—end of story.
There are no multidimensional arrays; you use arrays of arrays instead.
Pointers point to things; pointers to different types are themselves different types.
They have nothing in common with each other or any other types in C; there are no automatic conversions between pointers and other types.
Pointers can be used to simulate ‘call by reference’ to functions, but it takes a little work to do it.
Incrementing or adding something to a pointer can be used to step along arrays.
To facilitate array access by incrementing pointers, the Standard guarantees that in an n element array, although element n does not exist, use of its address is not an error.
Pointer arithmetic
Not only can you add an integral value to a pointer, but you can also compare or subtract two pointers of the same type. They must both point into the same array, or the result is undefined. The difference between two pointers is defined to be the number of array elements separating them; the type of this difference is implementation defined and will be one of short, int, or long. This next example shows how the difference can be calculated and used, but before you read it, you need to know an important point.
In an expression the name of an array is converted to a pointer to the first element of the array. The only places where that is not true are when an array name is used in conjunction with sizeof, when a string is used to initialize an array or when the array name is the subject of the address-of operator (unary &). We haven't seen any of those cases yet, they will be discussed later. Here's the example.
#include <stdio.h>
#include <stdlib.h>
#define ARSZ 10
main(){
float fa[ARSZ], *fp1, *fp2;
fp1 = fp2 = fa; /* address of first element */
while(fp2 != &fa[ARSZ]){
printf("Difference: %d\n", (int)(fp2-fp1));
fp2++;
}
exit(EXIT_SUCCESS);
}
freed Pointers
Calling free() on a pointer doesn't change it, only marks memory as free. Your pointer will still point to the same location which will contain the same value, but that vluae can now get overwritten at any time, so you should never use a pointer after it is freed. To ensure that it is a good idea to always set the pointer to NULL after free'ing it.
Regarding 1), reading an uninitialised value is undefined behaviour. Undefined behaviour means that the C standard does not specify what the compiler should do with your program when you attempt to read an uninitialised value, and therefore the compiler writer is free to pretend that uninitialised values will never be read from - and aren't required to account for that happening in a program.
Within the context of your code, you are presumably using GCC or Clang to compile your program. Your two pointer variables are local variables, and local variables are stored on the stack in GCC and Clang C code. The stack may contain 'random' bytes in it; a pointer on 64-bit computers is generally a 64-bit (8-byte) number that corresponds to an address of memory.
For each of the two pointer variables, these randomly initialised 8 bytes are interpreted as a memory address. You can attempt to read from this random memory address, and if you do this (and your program is allowed to access that particular memory address), you will read some garbage values that will be interpreted as the datatype that your pointer points to. For example, in your case, a regular int.
Regarding 4), not to add to what the accepted answer has already said - I'm curious whether, if you malloc a number of objects and you free one of them and you make no further memory allocations, you are not creating new malloc metadata since you have no new allocations. It would be reasonable that the free'd block does not have its contents mutated, right?
To my knowledge, free does not actually return memory to the operating system. Therefore, one would expect that the answer to the above be yes - the block is not mutated.
I am new to C and i have this question. why does the following code crash:
int *a = 10;
*a = 100;
Because you are trying to write 100 to the memory location 0x0000000A which is probably not allocated to your program. That is,
int *a = 10;
does not mean that the pointer 'a' will point to a location in memory having the value of 10. It means it is pointing to address 10 (0x0000000A) in the memory. Then, you want to write something into that address, but you don't have the "rights" to do so, since it is not allocated
You can try the following:
int *a = malloc(sizeof(int));
*a = 100;
This would work, although horribly inefficient. If you only need a single int, you should just put it into the stack, not the heap. On a 32-bit architecure, a pointer is 32 bits long, and an int is 32 bits long too, so your pointer-to-an-int structure takes up (at least) 8 bytes of memory space this way instead of 4. And we haven't even mentioned caching issues.
You need to assign the pointer to a memory location, not arbitrary value (10).
int cell = 10;
int *a = &cell; // a points to address of cell
*a = 100; // content of cell changed
See my answer to another question, about being careful with C.
I would like to propose a slight change in the use of malloc(), for all the answers that suggest using it to allocate memory for the int. Instead of:
a = malloc(sizeof(int));
I would suggest not repeating the type of the variable, since that is known by the compiler and repeating it manually both makes the code more dense, and introduces an error risk. If you later change the declaration to e.g.
long *a;
Without changing the allocation, you would end up allocating the wrong amount of memory ( in the general case, on 32-bit machines int and long are often the same size). It's, IMO, better to use:
a = malloc(sizeof *a);
This simply means "the size of the type pointed at by a", in this case int, which is of course exactly right. If you change the type in the declaration as above, this line is still correct. There is still a risk, if you change the name of the variable on the left hand side of the assignment, but at least you no longer repeat information needlessly.
Also note that no parenthesis are needed with sizeof when using it on actual objects (i.e. variables), only with type names, which look like cast expressions. sizeof is not a function, it's an operator.
Because you've never allocated any memory for a. You've just allocated some stack space for a pointer to a.
int *a = NULL;
a = malloc (sizeof (int));
if (a != NULL)
{
*a =10;
}
Will work.
Alternatively you could give a the address of some existing variable, which would work as well.
i.e.
int a* = NULL;
int b = 10;
a = &b;
This will now mean that doing something like
*a = 100;
will also set b to be == 100
Check out this:
http://home.netcom.com/~tjensen/ptr/pointers.pdf
The following line,
int *a = 10;
defines a pointer to an integer a. You then point the pointer a to the memory location 10.
The next line,
*a = 100;
Puts the value 100 in the memory location pointed to by a.
The problem is:
You don't know where a points to. (You don't know the value of memory location 10)
Wherever a points to, you probably have no right changing that value. It's probably some other program/process's memory. You thief!
Because You declare a pointer to int, initialize the pointer to 10 (an address) and then try to assign a value to an int at this address. Since the memory at address 10 does not belong to your process, You get a crash. This should work:
int *a;
a = malloc(sizeof(int));
*a = 10;
printf("a=%i\n", *a);
free(a);
Does this code even compile? 10 isn't convertible to an int *, unless you cast it like so:
int *a = (int *) 10;
*a = 100;
In that case, you're trying to write 100 into the memory address at 10. This isn't usually a valid memory address, hence your program crashes.
It's probably crashing because you are assigning the pointer to some part of memory which you don't have access to and then you're assigning some value to that memory location (which you're not allowed to do!).
You could also write it as:
int* a = 10;
*a = 100;
Note the different spacing on the first line. It's not a popular style, but I personally think it's clearer. It has exactly the same meaning to the compiler.
Then, read it out loud:
"Pointer-to-int 'a' becomes 10"
"Value-pointed-to-by 'a' becomes 100"
Substituting the actual value:
"Value-pointed-to-by 10 becomes 100"
... at which you realise that 10 is unlikely to point to a piece of memory you can use.
You would pretty much never assign to a pointer with a literal:
int* ptr = (int*)10; // You've guessed at a memory address, and probably got it wrong
int* ptr = malloc(sizeof(int)); // OS gives you a memory address at runtime
I guess there might be some very low level jobs where you directly specify absolute memory addresses. Kernel implementation for example?
Okay, trying to give the simplest explanation today, while trying to give you more detailed picture about it all. Lets add some parentheses shall we?
(int*) a = 10;
(*a) = 100;
You attempt to write four bytes into the address-range [10-13]. The memory layout of your program starts usually higher, so your application does not accidentally overwrite anything from where it could and still function (from .data, .bss, and stack for instance). So it just ends up crashing instead, because the address-range has not been allocated.
Pointer points to a memory location and C static typing defines a type for a pointer. Though you can override the pointer easily. Simply:
(void*) v = NULL;
Here we go further to things. What is a null pointer? It's simply pointer that points to address 0.
You can also give a struct type for your pointer:
struct Hello {
int id;
char* name;
};
...
struct Hello* hello_ptr = malloc(sizeof Hello);
hello_ptr->id = 5;
hello_ptr->name = "Cheery";
Ok, what is malloc? Malloc allocates memory and returns a pointer to the allocated memory. It has a following type signature:
void* malloc(size_t size);
If you do not have a conservative garbage collector, it is likely that your memory won't end up being freed automatically. Therefore, if you want to get the memory back into use from what you just allocated, you must do:
free(hello_ptr);
Each malloc you do has a size-tag in it, so you do not need to state the size of the chunk you pointed for free -routine.
Ok, yet one thing, what does a character string look like in memory? The one similar to "Cheery" for instance. Simple answer. It's a zero-terminated array of bytes.
0.1.2.3.4.5. 6
C h e e r y \0