So I'm aware that this question is most likely asked before, but after near an hour of searching I decided to ask all the same. Pointing me to a dublicate question which has already been answered would really be appreciated.
Then, programming in basic C, I'm curious to what happens to the array-elements when changing its pointer to pointing something else? Is it safe, without first freeing it? For instance,
int main()
{
const int size = 3;
int *p_arr = malloc(size * sizeof(int));
for( int i=0; i<size; i++)
p_arr[i] = i;
int arr[size] = {0,0,0};
p_arr = arr; // safe!?
// What happens to the data previously allocated
// and stored in *p_arr? Should one first call,
// free(p_arr)
// and then reallocate ..?
}
Essentially, changing the pointer will leave the data {0,1,2} in memory. Is this okay?
Thanks alot for any help!
Nothing happens to the data, except that it becomes unreachable ("leaked") and thus the memory is forever wasted, it can't be used for anything else until your program terminates (typically).
Don't do this, it's very bad practice to leak memory.
You should free() the memory when you no longer need it.
Also, the allocation can be written:
p_arr = malloc(size * sizeof *p_arr);
to remove the duplication of the int type, and lock the size to the actual variable. This is at least somewhat safer.
The array{0,1,2}is already in the memory,but you can't get it unless you point a pointer to the head address of the array again.
Related
I am trying to swap two arrays in C by pointing from array B to array A and then free up A so I am only left with array B with the contents of array A. Is this possible?
Code:
int *a = malloc(4*sizeof(int));
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
int *b = malloc(4*sizeof(int));
//Assign pointer from b to memory position of a so b[] = a[]?
Thank you in advance,
Wouter
#include <string.h>
#define ARRAY_LENGTH 4
// insert your code above here.. and as the other answer says you should
// always check malloc's return value to make sure it succeeded before
// continuing or you will seg fault. If it fails, you should gracefully
// handle the error
memcpy(b, a, sizeof(int) * ARRAY_LENGTH); // copies sizeof(int)*ARRAY_LENGTH bytes
// from the memory space pointed to by a
// to the memory space pointed to by b
free(a); // returns the memory pointed to by a to the heap
More information about memcpy can be found here. It's a highly optimized function for copying memory. If you only have 4 values, I doubt you'll see much performance difference between your own loop, memcpy, or simply manually-assigning (unrolling the loop) each value,, unless you're running this many thousands or millions of times.
And just a side note, as a general rule of thumb, you want to use malloc as sparingly as possible. The only times you should use it are if you don't know how much memory you'll need until runtime, or if you want the scope of the memory to persist outside of the function. Incorrectly managing memory is the source of many, many bugs that can be difficult to track down in large programs since they don't always manifest themselves at the same time in the same place the same way. Here, you don't show enough code for me to know exactly what you're doing. But you do know the size of the array ahead of time (4 ints), so unless you need these arrays outside of the function, just go ahead and put them in localized scope (on the stack in most systems):
int a[4];
int b[4];
// perform assignment to a
// perform copy to b
// do work on data
// ....
// now when the function ends, these arrays will automatically get destroyed, saving you the trouble
I'll just take you at your word that you have a good reason for copying the a array, as that's not evident from your code.
Finally, this was a dupe and neither of us should've answered it :)
How to copy one integer array to another
You can use a loop:
for (size_t i = 0; i < 4; i++)
b[i] = a[i];
Note: always check the return value of malloc() for failure.
If you create an array on the heap, with malloc(), you get a pointer which is like any other variable in that it may be assigned or copied. However there is only one memory buffer.
so
int *a = malloc(n * sizeof(int));
int *b = a;
means both a and b point to the same region of memory. That's called pointer aliasing, and it causes deep problems if you don't keep tight control of what you are doing. Generally if a points to the buffer, we should use a to identify it. A copy isn't useful to us.
If we have, as in your example
int *a = malloc(n * sizeof(int));
int *b = malloc(n * sizeof(int));
we have two buffers. So assigning b = a would make b point to a's buffer, and orphan the buffer that b is pointing to. Again, not what we want.
However if we do this
int *a = malloc(n * sizeof(int));
int *b = malloc(n * sizeof(int));
int * temp'
temp = a;
a = b;
b = temp
We have swapped a and b. b now points to the buffer a pointed to previously, a now points to the buffer b pointed to previously.
That's fine. And occasionally it's sensible to do that.
i have a little question in relation to the free() function of C.
I allocate in a program a multidimensional array with this code :
char **newMatrix( int N ){
int i,j;
char **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * N);
}
}
at the end of the program the array is full of characters.
So i do this to deallocate the memory.
void freeArray(char **a, int m){
int i;
for (i = 0; i < m; ++i) {
free(a[i]);
}
free(a);
}
My question is , how can I really check if the free() function works well , and deallocate all the memory?
I ask you because I have tried to print the matrix after the freeArray , and the result is that the values are still stored in the a[i][j] columns and rows .
Sorry if it will be a stupid question , i'm new of C programming!
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 array a after calling free(a) 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.
There are tools which are quite good at finding such errors, such as Valgrind.
free will not clear the memory for you. It just marks it as available for the OS to reallocate somewhere else. People tend to assign NULL to a pointer after freeing to prevent accidental reuse. If you want to be sure what your code is doing, you could memset the allocated space to a known value before freeing. To be honest, just print out how much data you mallocate and make sure you free the same size of data from the same pointer.
free() will only remove the reference to memory pointed to, by the pointer passed to it.
Once a pointer is passed to free() and the free() returns a success(which always is..), the pointer should never be used.
To avoid this usage, which is a illegal reference, a pointer variable should always be assigned NULL after it is passed to free().
If I understood you correctly you want to check if:
You don't reuse memory after freeing it
You freed all of the memory
It's not possible to do it directly from within language - however there are tools which can help. For example Valgrind can check both of those things (and much more). If you are on Windows tools like UMHD can be helpful but I haven't found any freeware replacement (though see also "Is there a good Valgrind substitute for Windows?" question)
UPDATE: I think I've answered my own question, except for some possible issues with memory leaks.
ORIGINAL QUESTION HERE, ANSWER BELOW.
Background: I'm doing some numerical computing, but I almost never use languages that require me to manage memory on my own. I'm piping something out to C now and am having trouble with (I think) pointer reference issues.
I have two arrays of doubles that are growing in a while loop, and at each iteration, I want to free the memory for the smaller, older array, set 'old' to point to the newer array, and then set 'new' to point to a larger block of memory.
After looking around a bit, it seemed as though I should be using pointers to pointers, so I've tried this, but am running into "lvalue required as unary ‘&’ operand" errors.
I start with:
double ** oldarray;
oldarray = &malloc(1*sizeof(double));
double ** newarray;
newarray = &malloc(2*sizeof(double));
These initializations give me an "lvalue required as unary ‘&’ operand" error, and I'm not sure whether I should replace it with
*oldarray = (double *) malloc(1*sizeof(double));
When I do that, I can compile a simple program (It just has the lines I have above and returns 0) but I get a seg fault.
The rest of the program is as follows:
while ( <some condition> ) {
// Do a lot of processing, most of which is updating
// the values in newarray using old array and other newarray values.
// Now I'm exiting the loop, and growing and reset ing arrays.
free(*oldarray) // I want to free the memory used by the smaller, older array.
*oldarray = *newarray // Then I want oldarray to point to the larger, newer array.
newarray = &malloc( <previous size + 1>*sizeof(double))
}
So I'd like to be, at each iteration, updating an array of size (n) using itself and an older array of size (n-1). Then I want to free up the memory of the array of size (n-1), set 'oldarray' to point to the array I just created, and then set 'newarray' to point to a new block of size (n+1) doubles.
Do I actually need to be using pointers to pointers? I think my main issue is that, when I set old to new, they share a pointee, and I then don't know how to set new to a new array. I think that using pointers to pointers gets me out of this, but, I'm not sure, and I still have the lvalue errors with pointers to pointers.
I've checked out C dynamically growing array and a few other stack questions, and have been googling pointers, malloc, and copying for about half a day.
Thanks!
HERE IS MY OWN ANSWER
I've now got a working solution. My only worry is that it might contain some memory leaks.
Using realloc() works, and I also need to be careful to make sure I'm only free()ing pointers that I initialized using malloc or realloc, and not pointers initialized with double * oldarray;.
The working version goes like this:
double * olddiagonal = (double *) malloc(sizeof(double));
olddiagonal[0] = otherfunction(otherstuff);
int iter = 1;
// A bunch of other stuff
while (<error tolerance condition>) {
double * new diagonal = (double *) malloc((iter+1)*sizeof(double));
newdiagonal[0] = otherfunction(moreotherstuff);
// Then I do a bunch of things and fill in the values of new diagonal using
// its other values and the values in olddiagonal.
// To finish, I free the old stuff, and use realloc to point old to new.
free(olddiagonal);
olddiagonal = (double *) realloc(newdiagonal, sizeof(double) * (iter+1));
iter++
}
This seems to work for my purposes. My only concern is possible memory leaks, but for now, it's behaving well and getting the correct values.
Here are some explanations:
double ** oldarray;
oldarray = &malloc(1*sizeof(double));
is wrong, because you don't store the result of malloc() anywhere, and since it is not stored anywhere, you can't take its address. You can get the effect that you seem to have had in mind by adding an intermediate variable:
double* intermediatePointer;
double** oldarray = &intermediatePointer;
intermediatePointer = malloc(1*sizeof(*intermediatePointer);
oldarray is now a pointer to the memory location of intermediatePointer, which points to the allocated memory slap in turn.
*oldarray = (double *) malloc(1*sizeof(double));
is wrong, because you are dereferencing an unitialized pointer. When you declare oldarray with double** oldarray;, you are only reserving memory for one pointer, not for anything the pointer is supposed to point to (the memory reservation is independent of what the pointer points to!). The value that you find in that pointer variable is undefined, so you have absolutely no control about what memory address you are writing to when you assign something to *oldarray.
Whenever you declare a pointer, you must initialize the pointer before you dereference it:
int* foo;
*foo = 7; //This is always a bug.
int bar;
int* baz = &bar; //Make sure the pointer points to something sensible.
*baz = 7; //OK.
Your answer code is indeed correct. However, it can be improved concerning style:
The combination of
int iter = 1;
while (<error tolerance condition>) {
...
iter++
}
calls for the use of the for() loop, which encapsulates the definition and incrementation of the loop variable into the loop control statement:
for(int iter = 1; <error tolerance condition>; iter++) {
...
}
In C, the cast of the return value of malloc() is entirely superfluous, it only clutters your code. (Note however that C++ does not allow the implicit conversion of void*s as C does, so int *foo = malloc(sizeof(*foo)) is perfectly valid C, but not legal in C++. However, in C++ you wouldn't be using malloc() in the first place.)
I ran into a rather weird problem,
I have the following code:
typedef struct{
char *a;
char *b;
char *c;
}Str;
typedef struct{
int size;
str array[]; //flexible array.
}strArr;
The purpose here is to allocate a,b, and c for the new element from the realloc.
StrArr *arr;
int arrSize;
arrSize = 1;
arr = malloc(sizeof(strArr)+sizeof(int)*arrSize);
arr->size++;
arr = realloc(arr, sizeof(strArr)+sizeof(int)*arr->size);
arr->array[arr->size-1].a = malloc(sizeof(char)*75);
arr->size++;
card = realloc(arr, sizeof(strArr)+sizeof(int)*arr->size);
The question is: whenever arr is realloc'd to be one bigger, do you have to allocate memory for the strings of the new element? This code will fail if it is run because it gives me glibc detected at the second realloc. What am I doing wrong? If i take off the malloc statement in the middle it runs. Also, if i try a strcpy into arr->array[arr->size-1].a, it would segfault.
Any help would be appreciated.
Thank you.
There are numerous issues with this code, enough to suggest that whatever you're experiencing can't be reproduced. Nonetheless, there are sufficient problems to cause instability (i.e. segmentation violations). I'm going to assume you meant to use a lowercase s in str rather than an uppercase S in Str; it only makes sense that way. Similarly for the lowercase s (which should be) in strArray.
At which point have you assigned arr->size a value in order for arr->size++; to be useful? That itself is a mistake, but that's interlaced into another mistake:
arr = realloc(arr, sizeof(strArr)+sizeof(int)*arr->size);
That turns out to be a major issue as you continue to use the uninitialised variable in critical pieces of logic, again and again, nonetheless, once that issue is resolved, the next mistake here is:
Anything that resembles the pattern X = realloc(X, Y); is suspicious. It's the Xes. Those should be different. You're not supposed to just replace the values like that. I mean, it'll work, kind of... but it's not much more effort to do it properly, and unless done properly, this won't be valgrind-friendly. That should be a big deal to you, because valgrind is a tool that helps us identify memory leaks!
You should store this into a temporary variable:
void *temp = realloc(X, Y);
... and then you can handle errors, perhaps by cleaning up and exiting properly:
if (temp == NULL) {
perror("realloc");
/* free(X); // what would valgrind cease complaining about? */
exit(EXIT_FAILURE);
}
... and replacing X with temp:
X = temp;
sizeof(int) should not be assumed to be the same size as sizeof str (whatever str is). Given the type of arr->array, I would expect sizeof str or, better yet, here's a nice pattern to keep in mind:
// X = realloc(Y, Z); or ...
void *temp = realloc(arr, sizeof *arr + arr->size * sizeof arr->array[0]);
// XXX: handle errors
The question is: whenever arr is realloc'd to be one bigger, do you have to allocate memory for the strings of the new element?
The strings themselves should be in a separate storage location to the list nodes. What is this? Strings and list nodes, in the same array?!
I suppose it might make sense if by strings you mean fixed-width, null padded fields. Fixing the width of the field makes expressing the array in a one-dimensional space much easier.
Otherwise, you should keep your strings allocated separately from your list nodes... in a manner with which the down-stream programmer has complete control over, if I may add, is kinda nice, though you lose that the moment you use realloc, malloc, etc (and thus the moment you use VLAs, hmmmm!)...
What am I doing wrong?
I think I've picked apart your code sufficing to say:
Initialise all of your variables before you use them. In this case, there are some variables pointed at by arr which are used without first being initialised.
Don't assume sizeof(int) and sizeof (/*any pointer type*/) have the same width. There are very real systems where this won't be true.
Remember to use that X = realloc(Y, Z); pattern, followed by error handling, followed by Y = X;.
I'm still not sure whether forcing down-stream programmers to rely upon malloc/realloc/etc and free is necessary, or even beneficial, here.
Also, if i try a strcpy into arr->array[arr->size-1].a, it would segfault.
Yes, well... there's that phantom arr->size-related issue again!
I'm studying for a test and I came across something I'm finding hard to understand. We're working with pointers and memory allocation, and I was just fooling around with things, trying to see what changed what. I have this bit of code:
int * arr[10];
for(i=0; i<5;i++)
{
int index = i;
arr[index] = malloc(sizeof(int*));
int i = 2 * index;
*arr[index] = i;
printf("arr [%d] = %d\n", index, *arr[index]); /* should be 0, 2, 4, 6, 8 */
}
But what I've found is that if instead of using *arr[index] = i, I use arr[index] = &i I don't need the malloc. I've always assumed that these two things were essentially the same thing, but there must be some key difference I don't understand to warrant the use of malloc with the one.
I'm actually confused why I need malloc at all here really. I'm fairly new with memory allocation and I don't really understand when it's supposed to be used (obviously) and was wondering if anyone could clear this up for me.
Try this code instead:
int * arr[10];
for(i=0; i<5;i++)
{
int index = i;
int value = 2*i;
arr[index] = malloc(sizeof(int*));
*arr[index] = value;
}
for (i=0; i<5; i++)
{
int index = i;
printf("arr [%d] = %d\n", index, *arr[index]); /* should be 0, 2, 4, 6, 8 */
}
If you make the change you suggest, you would now have undefined behavior. Whereas this code still is valid.
You'd have undefined behavior because *arr[0] now points to a piece of stack memory that has left scope.
Your malloc should actually be malloc(sizeof(int)). You're allocating space for an int, not for a int *.
Written this way:
*arr[index] = i;
Means: Copy the value of i to the memory location pointed to by arr[index] (that was allocated earlier in your code).
arr[index] = &i;
Means: Copy the address of i to arr[index].
In your code i is automatically created inside the for loop and only exists inside that loop. Once you leave the loop (scope) the memory used to store i is then free to part of any newly created variables.
As sharth suggests, try looking at the values outside the original for loop to see some interesting results.
Yeah I think it is hard to understand, because i gets redefined in the middle of the for. I'll rewrite the code right now. I wrote i instead of index and 2*i instead of the redefined i.
int * arr[10];
for(i=0; i<5;i++)
{
arr[i] = malloc(sizeof(int));
*arr[i] = 2*i;
printf("arr [%d] = %d\n", i, *arr[i]); /* should be 0, 2, 4, 6, 8 */
}
You don't acutally need dynamic memory here, you know that array 0-4 will be used. You need dynamic memory, when you don't know how mutch data will you need. This code is written, so that the rest of your code will still work, but there is no malloc.
int array[5];
int **arr=array;
The following code means, that array[index] should point to the memory adress i is stored in. It does not copy the value that is in i, so when you change i, or i gets deleted, this will cause this pointer to be faulty, and cause problems later. You should't do this.
arr[index] = &i
One key difference is that &i will cease to exist once i goes out of scope (or, rather, that piece of memory can be reused for something else... which probably won't contain what you thought it contains).
Edit: I say below you didn't show how i was declared. Actually, you redeclare it, hiding the original value if i used in the loop. Regardless, i is going to go out of scope at the end of the loop or, likely, when the routine ends.
You don't show how i is declared here. However, in most cases, it'd be a local variable or perhaps a parameter passed to a method. In either case, the space for that variable is declared on the stack. You can take the address of that variable with &i, but that variable is going to go away after the method ends and the code pops those values off the stack. You might get lucky and have that value remain untouched for as long as you need it. But the moment another method is called, that value is likely to be overwritten and boom, your program is at best going to behave incorrectly.
You could get away with this if i is declared globally.
Further, you're pointing to the same address even after changing the value of i. If, at the end of your routine, you printed out all of the values of your array, you'd see they were all the same value - the last value you put into the array. That's because each entry in the array points to the same location.