C - Reassign pointer inside of struct to pointer outside of struct - c

I have two pointers, each pointing to a different array. One of the pointers is inside of a struct, as follows:
typedef struct
{
int N; /* Number of Elements in array */
double *c; /* Pointer to an array */
/* Other members.... */
} CS;
The struct was initialized by:
CS->N = n; /* n is an integer of an initially unknown size */
CS->c = (double *)malloc(n * sizeof(double));
The pointer in the struct, CS->C, contains data that I no longer care about.
My other pointer was defined as follows:
double *alpha;
alpha = (double *)malloc(CS->N * sizeof(double));
I need to replace the contents of CS->C with alpha. I know I can do something naive like:
for (i=0;i<CS->N;i++) /* i is an integer */
CS->c[i] = alpha[i];
I could also use memcpy, like this:
memcpy(CS->c,alpha,CS->N * sizeof(double));
My understanding is that both of these methods will copy the contents from memory located at alpha to the memory occupied by CS->C. That being a very expensive operation, it would make more sense to simply change the assignment of CS->C to alpha.
How can I do this?
I've tried to reassign the pointer by doing like CS->C = &alpha, but this gives me the following warning "assignment from incompatible pointer type".
Note: This is using ANSI C89 under full compliance, i.e. the compiler options are: -Wall -pedantic -ansi
Edit 1
Freeing CS->c and assigning it to alpha by doing:
free(CS->c);
CS->c = alpha;
does not work. It causes every entry in CS->c to become equal to 0.0 and it results in my program seg faulting.
Edit 2
I think I realized why the method suggested in my first edit did not work. alpha is a temporary pointer, created and initialized inside of a function, so once that function is exited, the memory occupied by alpha is "freed". Since CS->c points to that memory, it is also freed. Upon this discovery, I think I will rework my code, such that alpha and CS-c are initially swapped, such that when they are switched again, the end order will be correct. Thank you all for you valuable input.

Just copy the pointer
CS->C = alpha;
Alpha is a pointer to double, CS->C too, types matches, you simply change the pointer.
/!\ Don't forgot to free the old CS->C ...

Free the old pointer and assing the new directly. (Not the adress of the new pointer)
The pointer in the struct, CS->c, contains data that I no longer
care about.
My other pointer was defined as follows:
double *alpha;
alpha = malloc(CS->N * sizeof(double));
...
free (CS->c);
CS->c = alpha ; alpha=NULL;

Related

Array of pointers to structs - why is malloc() required, why is direct field copies required?

I think I have a fundamental misunderstanding about memory and pointers in C. I'd like to ask why an array of pointers to structs needs malloc() called for individual elements of the array even though I'd think if they're getting initialized individually, then memory should be automatically allocated for them. Second, when filling up the array of pointers, it seems that it's necessary to copy the elements of the structs individually and simply copying the pointer to the struct itself doesn't work.
In other programs, I've been using structs and pointers a bit and I keep having to figure out the correct way to implement them, so I'd like to understand it intuitively rather than just taking for word "you just need to malloc() individual elements of the array"
/* suppose I have "typedef struct coord { int x; int y; } coord;" */
int num_rooms = 5;
coord* coordinates[num_rooms];
int i, j;
/* why is this required? in the following loop, coord[i] gets initialized,
and I thought memory automatically gets allocated on the stack because of
the initialization */
for (i = 0; i < num_rooms; i++) {
coordinates[i] = (coord*) malloc(sizeof(coord));
}
/* fill the array of coord pointers */
for (j = 0; j < num_rooms; j++) {
coord coordinate;
coord *coord_p;
coord_p = &coordinate;
coord_p->x = j;
coord_p->y = j;
/* this does not work. It just makes all array elements have the same struct elements. (the second question) Why does it require copying over individual field elements instead of copying the pointer?*/
//coordinates[j] = coord_p;
/* however, assigning individual elements doesn't cause segmentation fault */
coordinates[j]->x = coord_p->x;
coordinates[j]->y = coord_p->y;
}
If I uncomment coordinates[i] = coord_p; it ends up that all elements of the array have struct elements of the last initialized one. So if I printed every coordinate[i]->x and coordinate[i]->y it would saying '4 4' 5 times. But when I used the direct struct element copy, I get the correct output of '0 0, 1 1, 2 2, ...' if I printed it.
I expect that it should be fine to not allocate memory for individual elements of the array since they are initialized in a loop. I also expect that coordinates[i] = coord_p; should copy over the pointers value, letting something like printf("%d", coordinates[0]->x); work properly. However, in both cases I'm clearly misunderstanding something.
...why an array of pointers to structs needs malloc() called for individual elements of the array even though I'd think if they're getting initialized individually, then memory should be automatically allocated for them.
The simple answer is that C never allocates anything for you "automatically" in this sense.
One way to think about it is that C allocates just enough memory for your named variables, and that's it. If you say
int i;
C allocates enough memory for one int. If you say
double a[10];
C allocates enough memory for 10 doubles. If you say
int *p;
C allocates enough memory for one pointer-to-int, but it does not allocate any memory for that pointer to point to!
Almost without exception, when you declare pointers, it's your responsibility to think about the allocation of the memory that your pointers will point to. C never does that for you automatically.
In your specific example, when you said
coord* coordinates[5];
C allocated space for 5 pointers to coord -- but it allocated space for zero actual instances of coord. If, on the other hand, you had said
coord coordinatesa[5];
C would have allocated space for 5 actual instances of coord -- although you'd obviously use this array quite differently, since there are no pointers involved.
When you allocated 5 pointers, but no actual instances of coord, if you had tried to use one of the pointers, it would have been a serious error:
coord* coordinates[5];
coordinates[0]->x = 1; /* WRONG */
coordinates[0]->y = 2; /* WRONG */
One way to fix this would be to first make sure that coordinates[0] points somewhere:
coord* coordinates[5];
coordinates[0] = malloc(sizeof(coord));
coordinates[0]->x = 1; /* better */
coordinates[0]->y = 2; /* better */
Second, when filling up the array of pointers, it seems that it's necessary to copy the elements of the structs individually and simply copying the pointer to the struct itself doesn't work.
Ah, but when you copy pointers, you're carrying along the allocation of the source pointer, and losing the allocation of the destination pointer.
Taking my preceding example, and blending in part of your program, if you were to say
coord* coordinates[5];
coordinates[0] = malloc(sizeof(coord));
coord coordinate;
coord *coord_p;
coord_p = &coordinate;
coord_p->x = 1;
coord_p->y = 2;
coordinates[0] = coord_p;
This will "work", but it's wasteful and probably wrong. The memory allocated by the malloc call is never used, and when you say
coordinates[0] = coord_p;
the old pointer is overwritten and the pointed-to memory (that malloc so kindly gave you!) is lost.
After this assignment, the allocation of the memory pointed to by coordinates[0] is whatever coord_p's allocation was, which in this case is the single coord structure coordinate. As I say, this might seem to "work" at first, but if coordinate is a local variable that goes out of scope, or if you end up re-using it for all 5 coordinates in your coordinates array, you're going to have problems.
If, on the other hand, you say
*coordinates[0] = *coord_p;
or, equivalently,
coordinates[0]->x = coord_p->x;
coordinates[0]->y = coord_p->y;
now you're fetching data from the coord pointed to by coord_p, and safely copying it to the memory pointed to by coordinates[0]. Having done so, you've (a) properly used the memory you allocated for coordinates[0] to point to, and (b) insulated yourself from whatever happens later to the memory pointed to by coord_p.
But having gotten this far, in this case, we don't have to use the intermediate coord_p pointer at all. We could just as well say
coord coordinate;
coordinate.x = 1;
coordinate.y = 2;
*coordinates[0] = coordinate;
or, equivalently,
coordinates[0]->x = coordinate.x;
coordinates[0]->y = coordinate.y;
I'd like to ask why an array of pointers to structs needs malloc()
called for individual elements of the array even though I'd think if
they're getting initialized individually, then memory should be
automatically allocated for them.
It really isn't much different from having one pointer and allocating memory for it using malloc. Except instead of one pointer you have a whole array of pointers, so instead of just doing it once, you do it for each element of the array.
There's a problem with this part:
for (j = 0; j < num_rooms; j++) {
coord coordinate;
coord *coord_p;
coord_p = &coordinate;
coordinates[j] = coord_p;
}
coord coordinate is not dynamically allocated, so it's only valid until the end of the scope. At the end of the for loop, it becomes invalid. You save its pointer in coord_p and write that pointer to your array, but those pointers are all invalid afterwards.
But you already allocated memory for all the pointers, so you don't need to allocate any more. Just do this:
for (j = 0; j < num_rooms; j++) {
coordinates->x = j;
coordinates->y = j;
}
/* however, assigning individual elements doesn't cause segmentation fault */
coordinates[j]->x = coord_p->x;
coordinates[j]->y = coord_p->y;
The reason why this part works is that you're copying over the values of coord to your coordinates objects. Sure, coord becomes invalid at the end of the loop, but you made a copy of the values, which is fine.
I also expect that coordinates[i] = coord_p; should copy over the
pointers value, letting something like printf("%d", coordinates[0]->x); work properly. However, in both cases I'm clearly
misunderstanding something.
It copies the value of the pointer (not the object that is being pointed to, just the value of the pointer). The object that is pointed to isn't affected by that - it still has the same lifetime, which in this case is until the end of the loop. To actually copy the object being pointed to, do this:
*coordinates[i] = *coord_p;
This means "set the object pointed to by coordinates[i] to the object pointed to by coord_p".

Struct pointer syntax confusion

Hi i'm relatively new to c and was wondering if anyone could explain what exactly i'm doing with the following code.
I have a struct:
typedef struct free_list_header {
u_int32_t magic; // ought to contain MAGIC_FREE
vsize_t size; // # bytes in this block (including header)
vlink_t next; // memory[] index of next free block
vlink_t prev; // memory[] index of previous free block
} free_header_t;
and I'm initialising it within a function using the following...
void vlad_init(u_int32_t size)
{
int sizePow2 = pow(2, ceil(log(size)/log(2)));
memory = malloc(sizePow2*sizeof(char));
memory_size = sizePow2;
strategy = BEST_FIT;
free_header_t *freeHeader = (free_header_t*)memory;
freeHeader->magic = MAGIC_FREE; // the unique value
freeHeader->size = memory_size; // amount we malloc'd
freeHeader->next = 0; // position of next free block
freeHeader->prev = 0; // position of prev free block
free_list_ptr = 0;
}
my question is what exactly am i doing here and why is it necessary?
free_header_t *freeHeader = (free_header_t*)memory;
So... i'm declaring a new struct by pointing to it named "freeHeader"? and that is a pointer to it in the memory i have allocated? So this is a way of putting the struct into the malloc'd area to access it out of the function in which im initializing it?
Malloc returns a void pointer (type void*). This means it returns a pointer to a memory address and that pointer is not pointing to any specific type. So after the line:
memory = malloc(sizePow2*sizeof(char)); //sizePow2 is n bytes to allocate
memory is a pointer of type (void *).
free_header_t *freeHeader = (free_header_t*)memory;
On the left hand side here you are creating a pointer named freeHeader that points to a memory address containing something of type free_header_t
Since you explicitly said this pointer is pointing to an address of type free_header_t to you are casting the other side (currently of type void *) to match it as free_header_t *.
NOTE in C, this works but is not necessary. The compiler will automatically cast a void * to whatever type you need. However writing code like this is good practice, in C++ you need to explicitly do this.
free_header_t * freeHeader = (free_header_t*)memory;
you declared a pointer (not an actual struct) to free_header_t struct named freeHeader and you assigned it the value of the pointer named memory. since memory is a pointer to char and yours is a pointer to something else, you used casting.
You currently have only a pointer to an allocated area (of size sizePow2*sizeof(char) - note that the size of the struct should be less or equal to the size of the allocated memory).
Your code is essentially equivalent to:
free_header_t *freeHeader = malloc(sizePow2 * sizeof(char));
It's allocating a block of memory that contains sizePow2 bytes, and then using that as the address of a free_list_header structure.
The reason it uses the memory variable is because some other code is going to use the next and prev members as indexes into that block of memory. As the name implies, this structure just contains the data at the beginning of the memory block, the rest of the memory is managed with other structures.
memory = malloc(sizePow2*sizeof(char));
You are allocating some memory here. It would be good to just use
memory = malloc(sizeof(struct free_list_header));
to store an object of the structure.
free_header_t *freeHeader = (free_header_t*)memory;
Here you are declaring a pointer which would point to memory allocated earlier. You did not technically declare an object of the structure. And you are not putting the structure in to malloc-ed area, you are instead treating the malloc-ed area as an object of the structure.
free_header_t freeHeader = {0}; would be declaring an object of the structure.
Every time you call malloc() function, the operating system returns you a single memory address. When you cast this pointer to a specific type you tell to compiler that every element stored in the memory allocated will consume the size of the specified type and this get the things easier.
Let suppose that you declare a uint64_t* and the size of allocation it's 100 times the size of uint64_t, so you're asking for 800 bytes for the operating system, once the uint64_t takes 8 bytes. If you do not cast this pointer, every time you increase the address with your_variable++ your program will skip only one byte and you will get in the "middle of the number and will get a weird value", but if you cast your pointer to a uint64_t and increase the address with your_variable++ your program will skip 8 bytes, going directly to the next number.
In your example, you're telling to the operating system that your pointer will store types of free_header_t. You're not obligated to do it, but it is a very good practice.
And yes, if you return this address to another function, the other function can change the value stored in this memory area easily.
Hope it helps!

Pointer Copying for Two Dynamically Growing Arrays in C

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.)

Is there an easier way to cast a struct as a pointer to a struct

I have a unit test program i wrote to catch errors in the functions of an open source project before the initial compilation. All of the functions i need to test return a pointer to a struct(in this case bn_poly) while my variable is NOT a pointer. I know there must be an easier solution to this problem but after a bit of googling i came up with nothing, here is what i'm currently doing
/* only relevant part of code */
struct *bn_poly poly_summ;
unsigned i
poly_summ = (struct bn_poly*)bu_malloc(sizeof(struct bn_poly),"sum");
/* test multiplication and begin checking data */
*poly_summ = bn_poly_mul(&poly_summ,poly_eqn,poly_mul);
/* bn_poly returns a pointer to bn_poly, so i have to declare
* a temporary pointer to find the value. Is this the only way
* or is there a type cast method i am missing?
*/
what i would like to be able to do:
struct bn_poly poly_summ;
poly_summ = (somethingToConvertReturnVal)bn_poly_mul(&poly_summ,poly_eqn,poly_mul);
/* no memory allocation needed! */
I'm a little bit confused regarding what your question is But here's what i know about "casting" pointers.
the & symbol is the reference symbol, so &x gives you the address of x, or a pointer which points to x
the * symbol is the deference symbol, so suppose x is a pointer, *x gives you the value x points to
in your case, i think you want
struct bn_poly poly_summ;
poly_summ = *(bn_poly_mul(/*params*/));
as an additional note, by the looks of it, bn_poly_mul looks like it already allocates your struct and puts it on the heap. You don't even need to allocate it, in-fact doing so would result in a memory leak
Also, the fact that the first parameter of bn_poly_mul is &poly_summ is a little bit off-putting to me, so I'd have to see the function to know for sure

Memory management in C

Suppose I have a structure, and a pointer to a memory location p, how do I make sure that while creating an instance 'a' of the structure, it is placed into a memory chunk starting at p?
So I am passed a chunk of memory and I want to create a node at the beginning of it, so I need to make sure that the node is created at the beginning of it. (Note: I cannot use malloc, calloc, free, memcpy, or similar functions because I am writing code for a memory management system).
You don't really 'create' instances of structures in C like that. Assuming that p points to a block of usable memory, you can just treat p as a pointer to your structure type:
typedef struct {int x; long y;} a;
a *p2 = (a*)p;
int z = p2->x;
// or, if you don't want p2:
z = ((a*)p)->x;
Once p is cast (implicitly or explicitly as above), you can initialize the contents of your structure however you wish.
As an example, the following code will initialize a structure as you seem to request:
typedef struct {int x; float y;} tA;
void initA (void *p) {
tA *p2 = (tA*)p;
p2->x = 0;
p2->y = 3.14159;
}
int main (void) {
char bigmem[100];
initA (&(bigmem[0]));
return 0;
}
Don't get hung up on the main function above, it's only to illustrate how you can pass an arbitrary memory address to the function. In your real-world case, you will have the memory already allocated somehow.
If creation of the instance 'a' involves allocation of memory, then you can't make that allocation occur at memory pointed to by 'p'.
However, if by creation you mean initialisation of a structure in already allocated memory, then you should be able to pass 'p', typecast to a pointer to the structure, to the initialisation routine. But you will have to be careful that the memory pointed to by 'p' is large enough for the structure, is not being used for something else, and has the right alignment for the structure you are initialising.
If you are actually trying to do something else, you should post some code or go into a bit more detail.
just typecast the pointer to the type of your struct and you are done...
Hope it helps!
Basically, you take the address and cast it to a pointer of the appropriate type. The major problem you can run into is alignment: if the address isn't properly aligned for an object of that type, attempting to dereference the pointer can (and will) cause undefined behavior -- a typical reaction will be your program being aborted. If memory serves, a typical Unix kernel will give you an error message about a "bus error".
You can't control where the allocator will allocate memory from, but you can make a temporary instance (on the stack) and copy it into where p points with memcpy.
(Assuming p points to validly allocated memory, large enough for your structure and aligned appropriately.)
typedef struct {int x; long y;} A;
// Populate the members individually
A *aPtr = malloc(sizeof(A));
aPtr->x = 1;
aPtr->y = 2;
or
A *aPtr = malloc(sizeof(A));
A a;
a.x = 1;
a.y = 2;
// Use C's inherent "assignment == copy by value" capability
*aPtr = a;
or
A *aPtr = malloc(sizeof(A));
A a;
a.x = 1;
a.y = 2;
// Copy the memory yourself
memcpy(aPtr, &a, sizeof(A));
Feel free to replace my malloc with your own malloc.
Sounds like you are trying to do something similar to C++ placement new.
I think you confusing C with higher level languages. You never instantiate structs. You just allocate a bunch of memory and then cast those to a a struct pointer. Alternatively you allocate it on a stack which just means that compiler reserves so many bytes for you to use.
Code example for what Alex says:
struct foo {
int a;
char *b;
float c;
};
struct enough_space_for_a_foo {
char a[sizeof(struct foo))];
};
int main() {
// region of memory, which in the real code someone else is giving us
struct enough_space_for_a_foo memory_region;
// temporary object
struct foo tmp = {10, "ten", 10.0};
// copied to the specified region
memcpy(&memory_region, &tmp, sizeof(struct foo));
}
So, an arbitrary memory region now contains the same values as if it had been initialized as a struct foo, using the initializer expression {10, "ten", 10.0}.
If your struct doesn't need initializing with particular values, then you don't need to do anything. A region of memory in C basically is an instance of a struct if you choose to think of it as one (and it's big enough, and correctly aligned). There are no constructors, so just cast the pointer and get on with filling in the fields.
You asked just the right person. Not specifically, of course.
The answer depends on your OS. If you truly can't use anyone else's memory stuff, then you have your work cut out for you. You will have to make some kind of heap structure(s), perhaps some free list allocators for fixed size, and figure out what the OS has to offer. You have VirtualAlloc in windows and you have brk or similar in unix.
If this is really homework, this is way too much work if this is a single semester assignment.
Of course if all you want to know is how to prepend allocation size to what you return, just do whatever your code normally is, then put your value at the front, then advance the pointer by one and return that.

Resources