pointer to a structure within a structure in C - c

I have a structure (let's call it structure1) which holds a pointer to another structure (structure2), this way.
typedef struct structure{
structure2 *pointer
}structure;
structure structVariable;
structVariable.pointer = functionThatReturnsAPointerToStructure2Variable();
The thing is, as the program changes context (for example, when calling functions), the return value of the following code changes
structVariable.pointer->someAttribute
Any idea of why this might be happening? If you need more info please ask. Thanks!
MORE INFO
This is the real-deal
structure would be this
typedef struct CPU{
int variableCounter;
int instructionPointer;
char *currentInstruction;
t_list *dataDictionary_list;
u_int32_t currentContext;
PCB *assignedPCB;
CPU_STATUS status;
}CPU;
And this is how I assign the pointer (PCB *pointer)
PCB *pcb_createFromScript(const char *script){
t_medatada_program *metadata = metadatada_desde_literal(script);
PCB *pcb = malloc(sizeof(PCB));
pcb->instructionCount = metadata->instrucciones_size;
pcb->tagCount = metadata->cantidad_de_etiquetas;
pcb->functionCount = metadata->cantidad_de_funciones;
int codeSegmentSize = strlen(script);
int tagIndexSize = 0;
if(metadata->etiquetas != 0){
tagIndexSize = strlen(metadata->etiquetas);
}
int instructionIndexSize = metadata->instrucciones_size * sizeof(t_intructions);
pcb_getSegments(pcb,1024,codeSegmentSize,tagIndexSize,instructionIndexSize);
pcb->currentContext = pcb->stackSegment;
pcb->variableCounter = 0;
memory_write(pcb->codeSegment,0,codeSegmentSize,script);
memory_write(pcb->tagIndexSegment,0,tagIndexSize,metadata->etiquetas);
memory_write(pcb->instructionIndexSegment,0,instructionIndexSize,(void *)metadata->instrucciones_serializado);
pcb->uniqueId = (int) random();
return pcb;
}
And then I assign it this way (myCPU is global), that's why I call it inside cpu_getPCB without passing it as a parameter
cpu_getPCB(*dummyPCB);
void cpu_getPCB(PCB myPCB){
myCPU.currentContext = myPCB.currentContext;
myCPU.assignedPCB = &myPCB;
}

Here is some speculation.
If you are modifying the object that structVariable.pointer points to in some function, then when you try to read structVariable.pointer->someAttribute, that value will change to reflect to modification to the object.
Another possibility, as the other answer mentioned, is that structVariable.pointer is pointing to local memory (stack memory for a function) which can easily be overwritten on a new function call. That can be corrected by using malloc to do heap allocation instead of stack allocation.
Here is the first and most obvious issue. You are taking the address of a parameter and assigning it to myCPU.assignedPCB.
Since C is pass-by-value, you have copied it instead of capturing the original. Moreover, the parameter has the same lifetime as a local variable, and will go away when the function returns.
void cpu_getPCB(PCB myPCB){
myCPU.currentContext = myPCB.currentContext;
myCPU.assignedPCB = &myPCB;
}
You can fix it by passing a pointer instead, since you are in C and do not have access to the reference type.
void cpu_getPCB(PCB* myPCB){
myCPU.currentContext = myPCB->currentContext;
myCPU.assignedPCB = myPCB;
}

The "structure2 *pointer" will be pointing at a piece of memory that will disappear when you change context. Allocate the Structure2 variable and free it when it's no longer needed

Related

Passing a struct to void* param then copying it to a void*, reconstructing gives garbage value

I am really confused with passing my struct to void pointers, I'm not sure which one can be assigned directly and which one should be memcpyed, I've tried a lot of combinations but it does not seem to work. Any help would be very appreciated!
This is my C code
struct SomeStruct {
int a;
char name[10];
};
void *randoms[10];
void transferFunction(void* data, int index) {
// This function copies data to randoms[index]
// I would like to have the whole struct's data in randoms[index]
memcpy(&randoms[index], data, sizeof(struct SomeStruct));
}
struct SomeStruct *ss = malloc(sizeof(struct SomeStruct));
ss->a = 1;
strcpy(ss->name, "abc");
transferFunction(ss, 0);
My goal is to have the randoms[index] having the struct's data as another function is going to read from it, as shown below, but I am unable to retrieve the struct data correctly, it gives me some garbage value
void readFunction() {
struct *SomeStruct ss = malloc(sizeof(struct SomeStruct));
memcpy(ss, &randoms[index], sizeof(struct SomeStruct));
printf(ss->name);
}
Does anyone knows how to solve this problem? Thank you very much!!!
You can not "copy in to a void".
A void * can contain a memory address, but does not contain any information about the size of the data at that address.
Also, it can not contain any data, only an address!
In this line:
void *randoms[10];
You create an array that can hold 10 addresses.
You never initialize this array, so it will start out all zeroes (this only works for global variables in C).
You can put the address of your structure in to the array, like so:
random[0] = (void*)ss;
However, this does not transfer any data, so if you free the original structure (ss) your data is gone, and the address in random[0] is illegal.
If you want to transfer data you need to create array of struct SomeStruct or you need to allocate another SomeStruct, store its address in random[0] then memcpy to that address.
void transferFunction(void* data, int size, int index)
{
randoms[index] = malloc(size);
if (randoms[index] != NULL) {
memcpy(randoms[index], data, size);
}
}
Your code has some problems:
struct *SomeStruct ss = ... should be struct SomeStruct *ss =.
You are not cheking the return value of malloc() (which may fail).
You are not freeing ss allocated with malloc(). You should call free() on ss.
My goal is to have the randoms[index] having the struct's data
Lev M.'s answer already answers this part.
as another function is going to read from it
Simply assign your void pointer to a SomeStruct pointer:
void readFunction(int index)
{
if (index >= 10) // Index out of range
return;
struct SomeStruct *ss = randoms[index];
printf("%s\n", ss->name);
}

Struct by value in loop

Say I have a function from another api that returns structs by value
struct foo{
int bar;
bool success;
}
foo getThefoo();
What happens in a loop if this function is called eg
int foolen = 0;
foo** foos;
do {
foolen++;
foos = realloc(foos,sizeof(foo*)*foolen);
foo myfoo = getThefoo();
foos[foolen-1]=&myfoo;
}while (/**something*//)
Does a new foo struct get allocated on the stack for each iteration?. Or is the initial allocation reused?. I ask because taking a pointer to that structure might be an unexpected value.
getThefoo is defined in an external library. So its not trivial to make that return a pointer to a food structure.
This won't work, you're storing the address of a local which will go out of scope, rendering the stored addresses useless.
The proper fix seems to be to not store pointers to struct foos in the array, but just storing them directly:
struct foo *foos = NULL;
size_t foolen = 0;
do {
++foolen;
foos = realloc(foos, foolen * sizeof *foos);
foos[foolen - 1] = getTheFoo();
} while(something something);
Of course, the usual caveats apply:
It's more efficent to call realloc() less often, by over-allocating and tracking array length and array allocated space separately.
realloc() can fail, the above loses the old allocation (if any) when that happens.
Note that structures are values and thus fully assignable, so that's what we do.

C variable assignment to array element

Quick question on how a variable is assigned the value of an array element. Trying to make sure my code uses minimal memory.
If I have a predefined array of structs and want to create a reference to one element of the array, how do I create the variable so that it's passed by reference as opposed to value? I've searched around for this but perhaps my search string isn't what it needs to be.
for instance
#myfile.h
typedef struct {
uint8_t abba;
uint8_t zabba;
} mystruct;
extern mystruct mystructs[2];
#myfile.c
mystruct mystructs[2] = {
{.abba=0,.zabba=1},
{.abba=2,.zabba=3}
};
void myfunc1() {
mystruct ms1 = mystructs[1];
printf("%d", ms1.abba);
ms1.zabba = 5;
}
void myfunc2() {
printf("%d", mystructs[1].abba);
mystructs[1].zabba = 5;
}
So my questions are as follows:
When I create ms1 in myfunc1, is it just a reference to mystructs[1]? or does it copy the element into ms1?
Will myfunc1 and myfunc2 yield the same results in memory usage?
will ms1.zabba = 5 actually update mystructs[1].zabba?
When I create ms1 in myfunc1, is it just a reference to mystructs[1]?
No, it's a copy.
or does it copy the element into ms1?
Yes.
Will myfunc1 and myfunc2 yield the same results in memory usage?
No. (To be more elaborate: myfunc1 creates a local object of type mystruct ("on the stack"); after leaving the function everything is back as before, so no harm done. The structs are not big, so no problem. On PCs you could get a problem with things that are big (MBs) or expensive (e.g. socket connections).)
will ms1.zabba = 5 actually update mystructs[1].zabba?
No, since ms1 is a copy.
You may want to use pointers or references.
It's a copy. You need to use a pointer to actually modify the remote struct :
void myfunc1() {
mystruct *ms1 = &mystructs[1];
printf("%d", ms1->abba);
ms1->zabba = 5;
}

Assigning memory to a pointer to struct

In a program I am developing I have this structure:
typedef struct _event {
int id;
char title[30];
char desc[60];
int state;
} event;
In a certain part of this program I will use a function who requieres a pointer to this struct.
void event_foo(event *e)
{
/* Something will be done on this function,
with certain parameters of the pointer to the struct are needed */
}
But before accessing this function, I requiere to assign memory to this pointer to the struct.
int main()
{
event newevent;
/* In some place before invoking the function,
memory assignation is required */
event_foo(&newevent);
return 0;
}
¿Any suggestions to do it?
This:
event newevent;
creates a stack allocated instance of event, with memory already provided for it. This memory will be valid until newevent goes out of scope. If event_foo() is going to read any members of newevent and not just update them then you must initialize the members of newevent before calling event_foo().
If you had declared a pointer to event:
event* newevent;
then it would be necessary to allocate memory for newevent before accessing its members:
newevent = malloc(sizeof(*newevent));
in this case the memory for newevent exists until free(newevent) is called.
The way you did is correct
the declaration you did
event newevent;
is allocating static memory for newevent with type event
and when you called the function
event_foo(&newevent);
adding & at the beginning of newevent that means that you have provided the address (pointer) of newevent as input argument for the function
Into the function you can modify the parameters of the structure
Example
void event_foo(event *e)
{
e->id = 5;
strcpy(e->title, "any string");
strcpy(e->desc, "any string2");
e->state = 1;
}
And in the main() and after calling the event_foo(), you can access to your data in this way
event_foo(&newevent);
printf("id = %d\ntitle = %s\ndesc = %s\nstate = %d\n",
newevent.id,
newevent.title,
newevent.desc,
newevent.state);
return 0;
if e is needed only to point to the object passed as argument then there is no need to assign memory to it.through pointer we are directly accessing the objects memory location so we can do any changes directly to the members of the passed object

Changing a variable of a structure in C

Am I correct to say that if I want to change the content of a variable in a structure I have to give a pointer to the structure, using a different function to change the struction, like this:
Struct:
typedef struct data{
int row;
int column;
}data;
the var in the struct changer function:
struct data* init_maze(void) {
data information; //init information struct
data *infoPoint; //int information struct pointer
int row = 6;
int column = 10;
infoPoint->row = row; //not working but should be updating information
infoPoint->column = column; //same as above
return infoPoint;
}
But this is not working as intended. The code breaks and nothing happens. Could anyone please explain what I am doing wrong.
infoPoint should be declared as:
data* infoPoint = malloc (sizeof(data));
Then this code should work:
infoPoint->row = row; //not working but should be updating information
infoPoint->column = column; //same as above
And function init_maze doesn't need struct prefix:
data* init_maze(void)
data information;
is also unused
Another answer covers using pointers properly, but for different approach, you can pass structs around just like simple variables, so consider this version:
struct data init_maze(void) {
data information;
information.row = 6;
information.column = 10;
return information;
}
This is not as efficient as passing pointers around, but for most practical purposes and in most cases difference is irrelevant. And here size of this struct is two integers, which puts it solidly in this category.
Ask yourself first, what you want to accomplish here.
For example, you declare "data information" and you never use it. You don't even point "infoPoint" to anything before you manipulate it. Since you wrote nothing of a "SEGFAULT", I guess you are omitting some code?
Anyway. Do you want to create a new "data" struct and return it with some initial values? Then you have to either:
A) allocate some memory and return a pointer to this piece of memory on the heap (which must be allocated with malloc (or similar) and deallocated with free at some point"
B) You can take a pointer to a struct data as parameter and put your values in there.
data *init_maza(void) {
data *infoPoint = malloc(sizeof(struct data));
data->row = 6;
data->column = 10;
return data;
}
void init_maze(data *outp) {
outp->row = 6;
data->column = 10;
}
You can call B) with a pointer to a struct data on the stack or heap:
data foo;
data *bar = malloc(sizeof(struct data));
// Initialize
init_maze(&foo);
init_maze(bar);
Note the ampersand '&', the 'address-of' operator.
You can also use a pointer to pointer parameter so you still can return something else, like an error code. Used very often:
int init_maze(data **d) {
*data = malloc(sizeof(struct data));
(*data)->row = 6;
(*data)->column = 10;
return 0;
}
Your sample code is trying to modify an uninitialized pointer to a struct, so infoPoint->row = row; is an invalid operation since infoPoint is not initialized.
You could change your init function like this:
void init_maze(data *infoPoint) {
infoPoint->row = 6;
infoPoint->column = 10;
}
Then use it like this:
int main()
{
data information;
init_maze(&information);
}
data information; will allocate your struct on the stack, and you can pass a pointer to it for init_maze to do its job.

Resources