Learning dynamic memory allocation - c

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.

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;

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;
}
.

load data to struct and display, 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.

ANSI C Memory allocation for pointer to struct throws non-fatal run-time error

I am using ANSI C code, generated from a code generator that produces several layers of nested struct as well as function prototypes with argument lists that use pointers to the top layer struct for passing or accessing data located in the inner mmost struct.
Because the function prototypes pass pointers to struct, the application must allocate memory to access or write data to the inner most struct members. I am seeing the problem when attempting to allocate memory for the pointer to the second nested struct.
The actual error message I get is a non-fatal, run-time:
"Not enough space for casting expression to 'pointer to struct data'."
I am not explicitly casting anything, so I suspect the implementation of malloc() may have an assert that generates the message when it sees some condition. The wording of this error may be specific to my environment (I am using LabWindows/CVI) but I would be interested in hearing of results of other ANSI C compilers as well.
Here is a simplified, complete, code snippet that should compile, build and run (up to the error location, which is commented in-line)
I would appreciate comments on the cause of my error, and suggestions on how to fix it.
#include <ansi_c.h> //specific to LabWindows/CVI - change as needed for your environment
struct request
{
struct data *pData;
};
struct data
{
char *wsDate;
char *wsDuration;
char *wsFailures;
int __sizeM_Details;
struct details *M_Details;
};
struct details
{
char *wsStep;
char *wsTestDesc;
char *wsLowLim;
};
typedef struct request REQUEST; // from mtdf function prototype request argument (4)
typedef struct details DETAILS; // member of REQUEST - _ns1__MTDFData_MTDFDetail
void allocate(REQUEST *a, int numRecords);
void freemem(REQUEST *c, int numRecords);
int main(void)
{
REQUEST b, *pB;
pB = &b;
allocate(pB, 10);
freemem(pB, 10);
return 0;
}
void allocate(REQUEST *c, int numRecords)
{
DETAILS m_Param;
REQUEST b;
struct data d;
size_t size_c = sizeof(c);
c = malloc(size_c); //4 bytes
size_t size_c_data = sizeof(c->pData);
c->pData = malloc(size_c_data); //Breaks here - this is just a pointer,
//should it not just allocate 4 bytes
//and continue?
// Actual error message:
// "Not enough space for casting expression to 'pointer to struct data'."
c->pData->wsDate = calloc(80, sizeof(char));
c->pData->__sizeM_Details = numRecords;
c->pData->M_Details = calloc((numRecords + 1) , sizeof(m_Param));
}
void freemem(REQUEST *c, int numRecords)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
free(c);
}
There's several fundamental problems, here:
In allocate(), all that memory you're malloc()ing is being lost at the end of your function, because you're assigning it to a local variable, c, which gets destroyed at the end of your function. You never use the address of the struct with automatic storage duration that you pass into the function. If you're passing the address of an object with automatic storage duration, then you should malloc() memory for the members, but not for the struct itself, since it obviously already has memory.
Then, in freemem(), you attempt to free() the memory associated with b, which is a struct with automatic storage duration. You can only free() memory that you've dynamically allocated.
You have a curious comment in allocate(), "this is just a pointer, should it not just allocate 4 bytes and continue?". If you're on a system with 32 bit pointers, then that is indeed what you allocated, but c->pData is a pointer to struct data which looks like it needs 28 bytes on a 32 bit machine, so you should be allocating a lot more than 4 bytes for it. Lines like c->pData->wsDate = ... seem to indicate that you're well aware it's a pointer to a struct data, so it's really unclear why you think you should only be allocating 4 bytes. When you allocate memory for an ANYTHING * to point to, then you need to allocate enough memory for an ANYTHING, not for an ANYTHING *, i.e. enough memory for the thing it's going to point to. The fact that you're trying to assign the memory to your pointer in the first place proves that you already have the memory for your pointer, otherwise you wouldn't be able to do that (providing that you haven't messed up some previous allocation, of course).
You never check the return from malloc() and calloc(), and you should.
Names beginning with a double underscore are always reserved for the implementation, so you should call __sizeM_Details something else.
sizeof(char) is 1 by definition, so there's never any need to use it.
It's unclear why you're allocating memory for numRecords + 1 of your struct details, rather than just numRecords as would seem intuitive. Perhaps you're looking to set that last one to NULL as a sentinel value, but if you're already storing the number of records in your struct, then this isn't really necessary.
Here's what your code ought to look like:
#include <stdio.h>
#include <stdlib.h>
struct request {
struct data * pData;
};
struct data {
char * wsDate;
char * wsDuration;
char * wsFailures;
int sizeM_Details;
struct details * M_Details;
};
struct details {
char * wsStep;
char * wsTestDesc;
char * wsLowLim;
};
typedef struct request REQUEST;
typedef struct details DETAILS;
void allocate(REQUEST * c, const int numRecords);
void freemem(REQUEST * c);
int main(void)
{
REQUEST b;
allocate(&b, 10);
freemem(&b);
return 0;
}
void allocate(REQUEST * c, const int numRecords)
{
if ( !(c->pData = malloc(sizeof *c->pData)) ) {
perror("couldn't allocate memory for c->pData");
exit(EXIT_FAILURE);
}
if ( !(c->pData->wsDate = calloc(80, 1)) ) {
perror("couldn't allocate memory for c->pData->wsDate");
exit(EXIT_FAILURE);
}
if ( !(c->pData->M_Details = calloc(numRecords + 1,
sizeof(*c->pData->M_Details))) ) {
perror("couldn't allocate memory for c->pData->M_Details");
exit(EXIT_FAILURE);
}
c->pData->sizeM_Details = numRecords;
}
void freemem(REQUEST * c)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
}
If allocating automatic storage for b was a mistake, and you really do want to dynamically allocate everything, including your struct request, then it should look like this:
#include <stdio.h>
#include <stdlib.h>
struct request {
struct data * pData;
};
struct data {
char * wsDate;
char * wsDuration;
char * wsFailures;
int sizeM_Details;
struct details * M_Details;
};
struct details {
char * wsStep;
char * wsTestDesc;
char * wsLowLim;
};
typedef struct request REQUEST;
typedef struct details DETAILS;
REQUEST * allocate(const int numRecords);
void freemem(REQUEST * c);
int main(void)
{
REQUEST * b = allocate(10);
freemem(b);
return 0;
}
REQUEST * allocate(const int numRecords)
{
REQUEST * c = malloc(sizeof *c);
if ( !c ) {
perror("couldn't allocate memory for c");
exit(EXIT_FAILURE);
}
if ( !(c->pData = malloc(sizeof *c->pData)) ) {
perror("couldn't allocate memory for c->pData");
exit(EXIT_FAILURE);
}
if ( !(c->pData->wsDate = calloc(80, 1)) ) {
perror("couldn't allocate memory for c->pData->wsDate");
exit(EXIT_FAILURE);
}
if ( !(c->pData->M_Details = calloc(numRecords + 1,
sizeof(*c->pData->M_Details))) ) {
perror("couldn't allocate memory for c->pData->M_Details");
exit(EXIT_FAILURE);
}
c->pData->sizeM_Details = numRecords;
return c;
}
void freemem(REQUEST * c)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
free(c);
}

c basic struct help needed

I want to copy values into a struct using a pointer.
I keep getting segmentation fault from this small piece of code.
struct companyInfo
{
double sharePrice;
char companyName[100];
};
int main()
{
struct companyInfo * pdata = NULL;
strcpy(pdata->companyName, "sdfsd");
exit(0);
}
You aren't allocating any space for the struct, just a pointer that is null.
struct companyInfo * pdata = NULL;
pdata = calloc( 1, sizeof(struct companyInfo) );
if( pdata != NULL )
{
strncpy(pdata->companyName, "sdfsd", sizeof(pdata->companyName) - 1);
}
Note: calloc() will also zero out the memory for you, as opposed to malloc() which will just allocate. Also, you should check the return of these functions to make sure the pointer is not NULL.
Important: Any memory allocated using malloc(), calloc(), ex.. needs to be explicitly freed.
Example:
if( pdata != NULL )
{
free( pdata );
}
exit(0);
companyInfo is a pointer to a struct, and that pointer is pointing to NULL. So when you try to dereference it, you get the seg fault. You either need to use malloc to allocate some space for the struct pointer to point to, or declare the struct on the stack.
For the purposes of your exercise, I would go with option 2, as it's simpler. Just do:
int main()
{
struct companyInfo pdata;
strcpy(pdata.companyName, "sdfsd");
exit(0);
}
Because there is no * after companyInfo, pdata is not a pointer to a struct, but a struct.
Try this:
int main() {
struct companyInfo pdata;
pdata.companyName = "sdfsd";
}
You can set all variables in the struct at once:
struct companyInfo pdata = { 2.3425, "company" };
Tip: Use typedef before using a struct:
typedef struct companyInfo companyInfo;
So you don't have to type "struct companyInfo" every time. You can now simply use:
companyInfo pdata;
Hope I helped :)
The problem isn't with using a struct, but with trying to use a null pointer. Try something like this:
struct companyInfo *pdata = malloc(sizeof(*pdata));
strcpy(pdata->name, "sdfsd");

Resources