load data to struct and display, c - c

I am new to use C programming and trying to fill a structure and print the actual data stored in my struct. I'm stuck with segfault. see my sample code:
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h>
struct full_data
{
char *first_name;
char *last_name;
int *id_code;
};
struct owner
{
int *owner_code;
struct full_data tdata;
};
void display_my_output(struct owner *mydata)
{
printf("My data should be: \nfirst_name: %s\nlast_name: %s\nid_code: %d\nowner_id: %d\n",mydata->tdata.first_name ,mydata->tdata.last_name,mydata->tdata.id_code,mydata->owner_code);
}
int main()
{
int i;
struct owner *own;
for(i=0 ; i<4 ; i++)
{
if(i==0)
{
own->tdata.first_name = "PAUL";
}
if(i==1)
{
own->tdata.last_name = "ROOT";
}
if(i==2)
{
own->tdata.id_code =30001;
}
if(i==3)
{
own->owner_code = 2*i;
}
}
display_my_output(own);
return 0;
}
Am expecting my out put as:
My data should be:
first_name: PAUL
last_name: ROOT
id_code: 30001
owner_id: 6
Do i miss something in my code?

Yes, you are missing the fact that you declare and use a pointer to a struct owner, which means that you must initialize it.
So you could do
struct owner *own = calloc(1, sizeof(struct owner));
..
free(own);
but if you don't need to allocate it on heap then you could just allocate it on stack:
struct owner own;
own.tdata.first_name = ...;
Allocating it on the stack wouldn't prevent you from getting the address and pass it to display_my_output function. You just need to call it through display_my_output(&own);.

You need to initialize struct owner *own; using malloc() like this:
own = (struct owner*) malloc(sizeof(struct owner);
and don't forget to free memory at the end:
free(own);
Also, in both your structs, you are making a pointer to an integer rather than integer. I don't think you need an int*.

struct owner *own; declares a pointer to struct owner. Yes, now the compiler knows that the object own points to is a struct owner, but which struct owner is it pointing to? The compiler didn't know, because you didn't tell it.
In fact, an uninitialised pointer may point to an invalid/unavailable memory address, or contain a "trap representation". The result of either of them is undefined behaviour, which causes segfault in your case.
To fix this, write
struct owner *own = malloc(sizeof(struct owner));
The call to malloc() allocates a block of memory to hold a struct owner to own; thus it'll be pointing to valid memory.
Also, don't forget to add free(own) before main() returns, or you will get a memory leak.

Related

why am i getting this segmentation fault when trying to access a struct using a pointer?

I am trying to learn the nested structure. When I access it using a structure variable it works fine.
But when I try to access it using a pointer it says a segmentation fault.
#include <stdio.h>
#include <stdlib.h>
struct Vehicle {
int eng;
int weight;
};
struct Driver {
int id;
float rating;
struct Vehicle v;
};
void main() {
struct Driver *d1;
d1->id = 123456;
d1->rating = 4.9;
d1->v.eng = 456789;
printf("%d\n", d1->id);
printf("%f\n", d1->rating);
printf("%d\n", d1->v.eng);
}
You must initialize the pointer to an address of valid buffer before dereferencing that.
For example:
void main(){
struct Driver d; /* add this */
struct Driver *d1;
d1 = &d; /* add this */
Also I suggest you should use standard int main(void) in hosted environment instead of void main(), which is illegal in C89 and implementation-defined in C99 or later, unless you have some special reason to use non-standard signature.
You need to initialize the pointer before you can access what it points to. Here's one way to fix it:
struct Driver data;
struct Driver *d1 = &data;
d1->id=123456;
d1->rating=4.9;
d1->v.eng=456789;
printf("%d\n",d1->id);
printf("%f\n",d1->rating);
printf("%d\n",d1->v.eng);
Note the addition of data, and the initialization of d1 to point to it. When run, it produces:
123456
4.900000
456789
Another way to initialize it would be to use dynamically allocated memory via malloc, in which case you would later free the memory that you allocated.
You used pointer d1 without initialising it.
You need to initialise it first, for example with malloc:
struct Driver *d1 = malloc(sizeof(struct Driver));
if(NULL == d1)
{
perror("can't allocate memory");
exit(1);
}
// ... using d1
free(d1);
return 0;

Does fill structures from pointers make the acess to that struct undefined after free?

Let's say that we have the following case:
#include <stdio.h>
#include <stdlib.h>
struct test {
int a;
int b;
};
int main()
{
struct test *ptest = malloc(sizeof(struct test));
struct test jtest;
ptest->a = 3;
ptest->b = 2;
jtest = *ptest;
free(ptest);
printf("a: %d\nb: %d\n", jtest.a, jtest.b);
return 0;
}
As I've freed the pointer to ptest, and consequently the memory area that it refers to, my access to jtest is compromised after the free of ptest? Or when a make a dereference to assign the values of jtest it's made a copy of the values present on the address of ptest?
In C, if you're not using pointers, a copy is always made. So, when ptest is freed, jtest still has its own copy of the memory.

Learning dynamic memory allocation

i am a student and i try to teach myself code.
My question:
i have two structs:
struct1{
int a;
char name[20];}
struct 2{
struct struct1 *objekt;
int number;
double dNumber;}
I wanted to dynamically allocate memory in order to create at least one new Objekt(for lack of a better word). I know for example that i can allocate memory by using malloc or calloc. Which is fine. But how can i add a new object dynamically and via the console input, without defining a new struct? I am a complete novice and sorry. Thank you.
Consider the following example:
#include <stdio.h>
#include <stdlib.h>
struct Struct {
int a;
char name[20];
};
struct Struct struct1;
int main()
{
struct Struct *struct1_p;
struct1_p = &struct1;
struct1.a = 1;
printf("struct1->a = %d\n", struct1_p->a);
// Now let's create new structure dynamically
struct Struct * struct2 = malloc(sizeof(struct Struct));
// Now check if the allocation succeeded?
if(struct2 != NULL) {
//Success
//struct2 now is a pointer to the memory which is reserved for struct2.
struct2->a = 2;
} else {
// Allocation failed
}
printf("struct2->a = %d\n", struct2->a);
return 0;
}
This way, having the type of the desired object, you can dynamically create new object in the memory. Accessing the newly created object via pointer returned by malloc.
Remember that malloc returns void*, no need for explicitly cast.

How to modify pointer to structure inside void function

I tried to google my problem many times but never found an answer that fits my problem. I have to modify a pointer to a structure inside a function(fill it with data), and then use that pointer as an argument to another functions.
I have a text file that has multiple reports in it and I am supposed to count the reports and fill all the data to a pointer to a structure. Which isnt a problem, I allocated memory without a problem, got through the file without a problem and also filled the pointer. But I can't figure out how to use the filled pointer outside of the function.
struct report{
char name[50];
int id_number;
}
void function1(struct report **ptr){
//do stuff like count the number of reports in file
//and allocate memmory for pointer to structure
//and fill the pointer to structure with data
}
int main() {
struct report *pointer;
function(pointer);
//now I expect variable 'pointer' to be filled and ready to use by another functions
return 0;
}
Can you please suggest some solutions please? Thank you for your time and help.
Please have a look at the example:
#include <stdlib.h>
#include <stdio.h>
struct report{
char name[50];
int id_number;
};
void foo(struct report **ptr){
*ptr = malloc(sizeof(struct report)); // allocate memory
(*ptr)->id_number = 42; // fill the allocated memory
}
int main() {
struct report *pointer;
foo(&pointer); // important part - pass to the foo() pointer to the pointer.
printf("%d\n", pointer->id_number);
free(pointer); // do not forget to free the memory.
return 0;
}

Creating an Instance of a struct

I have this struct
struct FluxCapacitor{
unsigned char* c_string;
unsigned int value;
};
Now I need to create an instance of this struct. I googled this problem and found that I have to use something like this
typedef struct FluxCapacitor{
unsigned char* c_string
unsigned int value;
};
But I dont really understand the next step with malloc(). Can someone explain it to me?
You do not need malloc() to create an instance of a struct. And I would recommend that you avoid typedefing structures merely to reduce keystrokes. The extra keystrokes would only be saved in declarations and function prototypes (and maybe if you need to cast something), since you don't need the struct keyword elsewhere; the advantage is that when you see struct FluxCapacitor, you know exactly what it is. If you only see FluxCapacitor alone, you don't know if it is a typedef for a struct, or a union, or an integer type or what.
Note that the posted code was missing the semicolon at the end of the declaration. Also, it is unclear why you have unsigned char* c_string;. This may not allow assignment to a string literal. I have changed this in the code below. You can create a single struct like this:
struct FluxCapacitor
{
char *c_string;
unsigned int value;
};
...
struct FluxCapacitor fcap_1;
You can then assign values to the fields of fcap_1:
fcap_1.c_string = "McFly";
fcap_1.value = 42;
Note that you could also use designated initializers at the point of declaration:
struct FluxCapacitor fcap_2 = { .c_string = "Biff",
.value = 1985
};
If you need an array of FluxCapacitor structures, just declare one:
struct FluxCapacitor fcaps[2];
You can assign to the fields of each array member in a loop:
struct FluxCapacitor fcaps[2];
char *somestrings[] = { "McFly", "Biff" };
unsigned somevalues[] = { 42, 1985 };
for (size_t i = 0; i < 2; i++) {
fcaps[i].c_string = somestrings[i];
fcaps[i].value = somevalues[i];
}
Alternatively, you can use designated initializers here too:
struct FluxCapacitor fcaps[2] = { { .c_string = "McFly", .value = 42 },
{ .c_string = "Biff", .value = 1985}
};
Using malloc()
Since OP seems determined to use malloc(), it would be good to first recall that memory allocated with malloc() must later be deallocated with free(). Also note that malloc() can fail to allocate memory, returning a null pointer. Thus the result of a call to malloc() must be checked before attempting to dereference this pointer. The additional complexity should be avoided in favor of the above approaches unless OP has good reason to do manual allocation.
In the code below, the function create_flux_cap() takes a string and an unsigned int as arguments, and returns a pointer to a newly allocated FluxCapacitor structure with the arguments assigned to the appropriate fields. Note that since the FluxCapacitor structure is accessed through a pointer, the arrow operator is used instead of the dot operator.
Inside the function, the return value from the call to malloc() is checked before attempting assignment. If the allocation has failed, no assignment is made and a null pointer is returned to the calling function. Note that in the call to malloc(), the result is not cast, since there is no need for this in C and it needlessly clutters the code. Also observe that an identifier is used instead of an explicit type with the sizeof operator. This is less error-prone, easier to maintain if types change in the future, and is much cleaner code. That is, instead of this:
new_fcap = (struct FluxCapacitor *)malloc(sizeof (struct FluxCapacitor));
use this:
new_fcap = malloc(sizeof *new_fcap);
In main(), the return values from the calls to create_flux_cap() are checked. If an allocation has failed, the program exits with an error message.
The stdlib.h header file has been included for the function prototypes of malloc() and exit(), and also for the macro EXIT_FAILURE.
#include <stdio.h>
#include <stdlib.h>
struct FluxCapacitor
{
char* c_string;
unsigned value;
};
struct FluxCapacitor * create_flux_cap(char *, unsigned);
int main(void)
{
struct FluxCapacitor *fcap_1 = create_flux_cap("McFly", 42);
struct FluxCapacitor *fcap_2 = create_flux_cap("Biff", 1985);
/* Check for allocation errors */
if (fcap_1 == NULL || fcap_2 == NULL) {
fprintf(stderr, "Unable to create FluxCapacitor\n");
exit(EXIT_FAILURE);
}
/* Display contents of structures */
printf("%s, %u\n", fcap_1->c_string, fcap_1->value);
printf("%s, %u\n", fcap_2->c_string, fcap_2->value);
/* Free allocated memory */
free(fcap_1);
free(fcap_2);
return 0;
}
struct FluxCapacitor * create_flux_cap(char *str, unsigned val)
{
struct FluxCapacitor *new_fcap;
new_fcap = malloc(sizeof *new_fcap);
if (new_fcap != NULL) {
new_fcap->c_string = str;
new_fcap->value = val;
}
return new_fcap;
}
You need malloc for dynamic allocation of memory.In your case, both the types char and int are known to the compiler, it means the compiler can know the exact memory requirement at compile time.
For e.g. you can create a struct object like in the main function
#include<stdio.h>
#include<stdlib.h>
struct FluxCapacitor{
unsigned char* c_string;
unsigned int value;
};
int main() {
FluxCapacitor x;
x.c_string = "This is x capacitor"
x.value = 10
}
The x is of value type. You can make a copy and pass around this value. Also, observe we are using . notation to access its member variables.
But this doesn't happen at all time. We are not aware of future FluxCapacitor requirement and so above program will need more memory as while it is running and by using the malloc we can ask the compiler to provide us requested memory. This is a good place to use malloc, what malloc does is, it returns us a pointer to a piece of memory of the requested size. It is dynamic memory allocation.
Here's a simple example: let suppose if you need struct declaration of FluxCapacitor but don't know how many you will need, then use malloc
#include<stdio.h>
#include<stdlib.h>
typedef struct FluxCapacitor {
unsigned char* c_string;
int value;;
} flux;
// typedef is used to have the alias for the struct FluxCapacitor as flux
int main() {
flux *a = malloc(sizeof(flux)); // piece of memory requested
a -> c_string = "Hello World"; // Pointer notation
a -> value = 5;
free(a); // you need to handle freeing of memory
return 0;
}
.

Resources