How to gain access to objects locked behind doublepointer? (C) - c

In a homework task I must gain access to object specifics (i.e pID, Code), which are located in a structure. However, I need to link my function with the objects first (**ppObjects), but since I am dealing with a doublepointer, I seem to be having an issue.
It is worth noting that when I tried the same commands but function was PrintNewObject(HeaderC* pStruct4) it worked fine - so I am guessing it is an issue with me having to use doublepointer when dealing with pStruct4.
I have provided the code that I have tried below. While compiling it shows no error, but upon trying to print something from it, it says that obj is a nullpointer.
The function that I would like to link with ppObjects.
int InsertNewObject(HeaderC** pStruct4){
HeaderC* testinH;
for (testinH = *pStruct4; testinH != NULL; testinH = testinH->pNext)
{
int count = 0;
while (count < 26) //one for every letter in the alphabet, as ppObjects is an array
{
Object9* obj;
obj = (Object9*)testinH->ppObjects[count]; //the line that does not seem to properly define
printf("%lu", obj->Code); //running this line crashes my program
count++;
}
}
Header, where we can see that ppObjects is a doublepointer.
typedef struct headc
{
void **ppObjects; // Pointer to the array of pointers to objects.
// Objects may be of types Object1-10
char cBegin; // The first letter of ID of objects related to
// header is cBegin.
struct headc *pNext;
} HeaderC;
The object I was provided in the hometask is below. This is what I would get access to after defining
typedef struct ob9
{
char *pID;
unsigned long int Code;
Date3 *pDate3;
struct ob9 *pNext;
} Object9;
I get an error saying that obj is nullpointer when I try to print anything from obj.
If this is poorly worded, I am sorry. I tried my best to make this understandable yet not too long. Any help is appreciated!

Related

Struct and segmentation fault in c

I'm currently new to the struct and linked list. I'm trying to put the values of my array arr_dec[4] in a variable. My array is on a struct, and also in my init function. I think my problem is on the display function, in my if loop.
[EDIT] :
Hi, so I think I correctly changed my errors, but I still get a segmentation fault, and really I don't understand why I get it. If you could see what is wrong and how I can correct it it'll be great ! Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct Plane_dec Element;
struct Plane_dec
{
int array_dec[4];
int nbr_var;
struct Plane_dec *head;
struct Plane_dec *next;
};
void init(int nbr_caract) //It's my initialisation function, i want to initialize my linked list.
{
Element *plane_dec = malloc(sizeof(plane_dec));
Element *head = NULL;
Element *next = NULL;
plane_dec->var_num = 0;
plane_dec->arr_dec[0] = 2;
plane_dec->arr_dec[1] = 5;
plane_dec->arr_dec[2] = 1;
plane_dec->arr_dec[3] = 3;
return *head;
}
void display (int nbr)
{
int i = 0, variable = 0;
struct Plane var;
struct Plane_dec *plane_dec;
init(nbr_caract);
for(i = 0; i <4; i++)
{
variable = plane_dec->arr_dec[i];
printf("%d - ", variable);
}
}
int main()
{
int nbr;
prinft("Please select a number : ");
scanf("%d", &nbr);
display(nbr);
return 0;
}
My output is just : Segmentation fault (core dumped).
Among other problems that prevent compilation:
In display, you pass an uninitialized pointer to a pointer of Plane_dec (you declare a pointer and then pass its address) to init (which is stated to expect just a pointer!), and then within init you attempt to modify its fields.
If what you've been meaning to do is dynamically allocate a Plane_dec, then you need to actually do so: init needs to begin with a *plane_dec = malloc(...), and you need to modify its declaration to accept a pointer to a pointer to Plane_dec, and not just a pointer to Plane_dec.
If, on the other hand, what you've been meaning to do is just modify a local variable declared within display and then discard it when display finishes its run, then you don't want display's plane_dec to be a pointer (so remove the asterisk from the variable declaration).
Either way, the arr_dec you declare within init gets promptly discarded and doesn't have anything to do with the similarly-named field of the plane_dec variable, and nbr_var also doesn't do anything, as it is. (Also note that in display you attempt to access the arr_dec field of Plane_dec, but the field is named array_dec, not arr_dec.)
If this doesn't solve your problem, please make sure to provide more context about what you've actually been meaning to do, as well as post your error (textually, not as an image), and create a minimal reproducible example: make sure to copy the code in question into a brand new file and test that it compiles, and provide the error details based on that. It is quite likely that if you do all of this, you'll figure out the answers on your own; and if you don't, we'll be able to help a lot more efficiently.

Different variables of same name (C language)

FINAL EDIT: First of all, thank you guys for your patience. In the future I'll try to bring an MCVE to any questions I ask.
The program seems to be working fine now - I may have unwittingly deleted a typo or something.
This question annoys me quite a bit - I didn't choose to implement it this way, but it's required and I need to resolve it.
I've got a function that's supposed to read a piece of data from a struct, like this:
typedef struct {
int data;
char extraneous_stuff[];
} MyStruct;
...
//there's also a ParentStruct that holds a MyStruct array
...
void read_data(ParentStruct *parent, int which_MyStruct, int *data) {...
What I need to do is use the int *data as an out-parameter to copy the int data from inside a selected MyStruct. The problem I'm having, of course, is that both the out-parameter and the MyStruct field have exactly the same name. I found that trying to copy directly, i.e. *data = parent->array[which_MyStruct].data; compiled, but the data didn't actually get copied to the out parameter.
In order to hold to specifications I'm not supposed to change the names of the parameters here. Am I doomed?
EDIT: I included the following print statements inside the function:
printf("%d", *data);
printf("%d", parent->array[which_MyStruct].data);
and, having put
int n = 0;
void read_data(*parent, which_MyStruct, &n)
I got back
0
0
as a result.
EDIT 2:
OK, this is very weird. I have this:
MyStruct current = parent->array[which_MyStruct];
printf("%s", current.extraneous_stuff[0]);
printf("%d", *data);
printf("%d", parent->array[which_MyStruct].data);
and now suddenly "parent->array[which_MyStruct].data" has the appropriate value.
Maybe this is undefined behavior, because the only change I made was to include the print statement "printf("%s", current.extraneous_stuff[0]);" and the output changed.

Homework error: Dereferencing pointer to incomplete type

I am working on a homework assignment.
I'm running into the title error in this assignment. From what I've looked into so far, I know that there's a problem with the struct definition somewhere, but because that was done by my professor, I am inclined to think that it's something to do with the way I am calling the struct.
Here is the relevant code.
in main.c (where I'm getting the errors from):
#include "processes.h"
//...
Processes * proc = proc_create(filename); //line 90
// the struct I'm trying to create
//...
for(i = 0; i < proc->size; i++) // line 100, where I get the first error of
// dereferencing pointer to an incomplete type
{
//Some code
}
in processes.c (where struct Processes is defined):
struct Processes{
struct Proc *array; // array of Processes
int internal_size; // how big the array is total
int size; // how many valid Procs in the array
};
in processes.h:
typedef struct Processes Processes;
// Create your Processes struct using the filename of a schedule.txt
Processes * proc_create(char *filename);
If someone could please explain to me, exactly what this error means, and point me in the right direction to fixing it, that would be greatly appreciated! Also, If you need anything else, I'm happy to post other code. I was just pretty sure that this was the relevant code.
Since the header file doesn't contain the complete definition of the Processes struct (only a forward declaration), the compiler cannot possibly know how to access its members. Consequently, proc->size isn't meaningful inside the main.c file. You will have to move the entire definition of the struct into the header file if you want to use its members directly. (Or, if creating an opaque type is your concern, then write an accessor function that simply returns proc->size.)
Also, your proc_create() function should probably take a const char * argument.

C code passing struct into function Stack overflow

Okay so I'm having an issue with a current assignment (trust me this is a minuscule part of it) as we are required to write in C code and not C++, and we are not allowed to change certain parts of code. So I have a struct defined:
typedef struct someStruct {
int what;
int something[MAX];
int another[MAX];
} someType;
in main() I initialize all the values in a defined struct:
someType whatever, *whatptr;
EDIT:of course set the pointer to the struct, trying to simplify the code for the example It is present in my code already
whatptr = &whatever;
whatever.what = 0;
// initialize both arrays to hold 0 at all indexes
// Then I must call a function progRun()
progRun(); //I need to pass struct 'whatever' in some way
Now progRun() looks like this:
void progRun(){
printWhat(&whatever);
if (whatever.what == 0) {
//do stuff
}
}
I can't change anything inside this code except what parameters to pass inside the progRun() function and I can add stuff before printWhat(). I've tried changing progRun to
void progRun(someType *stptr)
then calling it in main as
progRun(whatptr);
but this causes a stack overflow issue for some reason, I've tried stepping through with a debugger and it only occurs when the function is called. Is there a better way to pass the 'whatever' struct to the function so it can be passed into progRun() and printWhat() and can access 'whatever.what'?
Any help would be greatly appreciated! in the meantime I'll try to figure it myself if I can.
EDIT: Something else must be wrong in the code even though everything else has compiled and ran perfectly fine until this code was added. If I can break down the code and find out what's wrong I'll update the question. And no I cannot post the whole code as it is an assignment (this isn't the goal of the assignment trust me it focuses on data forwarding and more, just need to get this basic thing working) Thank you for help everyone.
EDIT: the MAX number used in the struct for something[MAX] and another[MAX] was extremely large ( I left my desktop that I started this project with back home, I'm currently using an old laptop that can't handle large arrays). All the answers below, and some of the stuff I used before now works fine.
void progRun(someStruct *ptr) {
someStruct whatever2 = *ptr;
printWhat(whatever2);
if (whatever2.what == 0) { ...
}
whatptr = &whatever;
progRun(whatptr);
Your problem was that:
you need to pass a pointer to whatever, yet you were passing a variable (whatptr) that had absolutely nothing to do with whatever.
You need to first assign the pointer to whatever into your pointer variable.
You are not dereferencing the pointer in the function
Alternately, get rid of pointer variables:
void progRun(someType *stptr) {
printWhat(*stptr);
if (stptr->what == 0) { ...
}
progRun(&whatever);
Instruction
someType whatever, *whatptr;
is the problem:
*whatptr will not point to the struct whatever unless you do the assignment as follows:
whatptr = &whatever;
Alternatively you could dynamically allocate memory on the heap for a pointer to your struct whatever by using the malloc() function and pass the pointer returned by malloc to the function progrun:
whatptr = (someType*) malloc ( sizeof(someType) );
if (whatptr == NULL) exit (1);
//whatever you need to do with your code
progrun(whatptr); // call function like this
In this case of course you will need to dereference your pointer to access member elements of the struct by using the arrow -> operator:
whatpr->what = 0; // for example
Also, check these tutorials to understand both approaches:
link 1
link 2
If you can't change print and if statements then you should pass your function a copy of your struct:
void progRun( someType whatever ){ // <---Passing by copy
printWhat(&whatever);
if (whatever.what == 0) {
//do stuff
}
}
and in your main() you should just call the function like this:
someType whatever;
//assign values to members of the struct
progRun(whatever);
and do not need at all to define and assign a pointer to the struct.
Though passing variables to functions by copy (especially when they are objects composed by many variables such as a struct is) is not a good behaviour:
it will require an overhead to copy all member elements
your copy will have a limited scope, which means that any change you do to the variable inside of the function will be lost when your function ends and will not be reflected on variable at main scope

Pointer to pointer confusion

Edit: The reason queue is 2d is because I need a pointer of Command so that cmd can equal NULL. NULL == (void *). This is where I get confused though, and why I've come here. :)
To help try and figure out another problem I have in Python, I'm implementing a small test program in C. While I know a little, apparently I'm confused. I'm trying to write a simple queue to be used in asynchronous USB transfers. Something's not right with queue, as every command popped from the queue is the same. If I write queue[1024][0] as queue[1024][1] instead, the command alternates between two distinct commands, and the program crashes in command_thread_main. Apparently it doesn't notice that cmd should be NULL. Changing [1] any higher has no effect as far as I can tell. Any hints?
typedef struct Command {
void (*cb) (char *data, int size);
unsigned char *data;
int size;
} Command;
struct Command queue[1024][0];
int queueEnd = 0;
int queueStart = 0;
static void queue_push(void (*cb), unsigned char *data, int size) {
if (queueEnd >= 1024)
return;
queue[queueEnd]->cb = cb;
queue[queueEnd]->data = data;
queue[queueEnd]->size = size;
queueEnd++;
}
struct Command * queue_pop(void) {
if( queueStart > queueEnd )
return NULL;
return queue[queueStart++];
}
static void *command_thread_main(void *arg) {
struct Command *cmd;
while (!do_exit) {
if(locked) continue;
locked = 1;
cmd = queue_pop();
if(cmd != NULL)
cmd->cb(cmd->data, cmd->size);
}
}
I think you have a bug you need to fix before anything else. You have a 2D array of commands and have set one of those dimensions to zero!
struct Command queue[1024][0];
When you access queue you seem to treat it as a 1D structure. Should you declare it as :
struct Command queue[1024];
Don't you mean struct Command queue[1024];? (That is, no [0] or [1] or whatever.)
In queue_pop I think you should test for queueStart >= queueEnd.
You should implement a circular array.
Right now you store the struct itself in an array, not pointers to it. That is sensible. You'll need to change -> to . though:
queue[queueEnd].cb = cb;
queue[queueEnd].data = data;
queue[queueEnd].size = size;
(And hence queue_pop should return a variable of type struct Command (not struct Command *), and the main code should also be updated accordingly.)
Of course you can also pass pointers around, but with such a small struct/queue there's no actual need.
As others have pointed out, that 2D queue is definitely wrong. You need a 1D queue, and I suspect that what you want is an array of pointers:
Command * queue[1024];
I reommend you go a way and think about the problem a bit, draw some diagrams and then come back with clearer code and question.
Another problem is that you've declared queue as an array of structs, but you're using it as an array of pointers to structs by using the dereferencing -> operator instead of the membership . one.
I don't mean to sound snarky, but compiler warning flags (-Wall for gcc) are your friends.

Resources