Structures and dynamic memory in C - c

I'm a beginner in C.
I want to assign each person's info to an array of pointer that is *arr[2]
but I get an error message that is
'malloc' is not declared in this scope.
How can I fix it?
#include <stdio.h>
int main()
{
struct person {
char *name;
int number;
char gender;
};
struct person *arr[2];
arr[0] = (struct person *) malloc(sizeof(struct person));
arr[0]->name = "john";
arr[0]->number = 123;
arr[0]->gender ='m';
arr[1] = (struct person *) malloc(sizeof(struct person));
arr[1]->name = "jessica";
arr[1]->number = 456;
arr[1]->gender ='w';
printf("%s", arr[1]->name);
return 0;
}

A few inputs than just one.
Primarily:
The man page for malloc says that you need to include the header file: stdlib.h
#include <stdlib.h>
The one habit which would save you a lot of pain going ahead is to check if malloc() was successful or not. You must check the value returned by malloc().
arr[0] = malloc(sizeof(struct person));
if(arr[0] == NULL)
{
// Since malloc has returned NULL, requested memory is not allocated
// Accessing it is out of question
// Some error handling implementation
return;
}
Additionally, we should always return what we borrow, unless we don't crash all of sudden. Allocated memory needs to be freed. There are several examples on internet on how to de-allocate the dynamically allocated memory. A good start would be reading concepts like Memory Leakage and Dangling pointers.
The other suggestion would be:
If you look at the same (or the other) man page for malloc, you'd find that malloc returns a void pointer. So, you do not have to cast the malloc() result. There is this legendary post and a legendary answer which explains why not to cast.

You should include a header which defines malloc(). Usually, this would be stdlib.h.
You can use online help from cppreference.com or similar sites to get this information, and full documentation for the c libraries.

To actually use the function malloc,you should include the #include library which declares among other things the malloc(), calloc(), free() functions.

Related

double linked list in c send data from function

This is my code:-
typedef struct Frame
{
char* name;
unsigned int duration;
char* path; // may need to scan (with fgets)
}frame_t;
typedef struct Link
{
frame_t* frame;
struct Link* next;
}link_t;
void addNewFrame(void)
{
link_t* newLink = (link_t**)malloc(sizeof(link_t*));
printf(" *** Creating new frame ***\n\n");
printf("Please insert frame path:\n");
// newLink->frame->name = (char*)malloc(sizeof(char) * MAX_LEN);
fgets(newLink->frame->name, MAX_LEN,stdin);
printf("%s", newLink->frame->name);
}
I just need to add a data to name variable in the "Frame" link list, please help me by reviewing this code.
You want to allocate the right types here:-
link_t* newLink = malloc(sizeof(link_t)); //Pointer to Link st
if(newLink){
newLink->frame = malloc(sizeof(frame_t)); //Pointer to frame member
if(newLink->frame){
newLink->frame->name = malloc(sizeof(char) * MAX_LEN); //Pointer to name member
if(newLink->frame->name){
//Rest of your code
}
}
}
EDIT:-
1. As pointed out in comments there's no need to cast the pointer returned by malloc()
2. Another very imp point you may want to check validity of the pointers before de-referencing them
First. You don't need to cast void * so (link_t **)malloc(... can be only malloc(....
Second. You allocated enough memory for a pointer not for a struct. I think you mean malloc(sizeof(link_t)) or even better malloc(sizeof(*newLink))
Third newLink->frame is a pointer so you need to allocate data for it too, newLink->frame = malloc(sizeof(frame_t))
Fourth newLink->frame->name is still a pointer so you need to allocate data for it too. newLink->frame->name = malloc(MAX_LEN)
The confusion that you are doing is pretty common. When you say type *something you are allocating a pointer to type in the stack. A pointer needs to point to somewhere else or NULL, or bad things happen. This applies to structures too. If your structure has a pointer member you need to point it to somewhere else. The somewhere else is where the real "type" object resides.
This also applies to arrays. If you say 'int foo[10]' you are allocating ten integers in the stack. If you say int *foo[10] you are allocating ten pointers in the stack. If you say int **foo you are allocating one pointer in the stack. Again all pointers need to be initialized, I mean, they need to point to some valid object, allocated somewhere else in the memory.
I hope this helps.
Some other points.
Always check pointer coming from malloc, if allocation failed you'll receive NULL. Dereferencing NULL will break your program.
Always initialize memory coming from malloc, fill it with zeros or something.
Don't use _t suffix, is POSIX reserved.
I didn't test any of this.

How to allocate memory to struct pointer using malloc.h header?

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
struct student
{
char name[25];
int age;
};
int main()
{
struct student *c;
*c =(struct student)malloc(sizeof(struct student));
return 0;
}
What is the wrong with this code? I tried times by alternating this code to allocate memory to struct pointer. But this error comes when compiling:
testp.c:15:43: error: conversion to non-scalar type requested
*c =(struct student)malloc(sizeof(struct student));
^
I'm using mingw32 gcc compiler.
What is the wrong with this code?
Ans: First of all you change that "is" to "are", there are two major problems, atleast. Let me elaborate.
Point 1. You allocate memory to the pointer, not to the value of pointer. FWIW, using *c (i.e., de-referencing the pointer without memory allocation) is invalid and will result in undefined behaviour.
Point 2. Please do not cast the return value of malloc() and family in C. The cast you used is absolutely wrong and proves the authenticity of the first sentence.
To solve the issues, change
*c =(struct student)malloc(sizeof(struct student));
to
c = malloc(sizeof(struct student));
or, for better,
c = malloc(sizeof*c); //yes, this is not a multiplication
//and sizeof is not a function, it's an operator
Also, please note, to make use of malloc() and family , you don't need the malloc.h header file. These functions are prototyped in stdlib.h.
EDIT:
Suggestions:
Check for success of malloc() before using the returned pointer.
Always free() the memory once the usage is over.
The recommended signature of main() is int main(void).
This worked (on C and C++).
Since you originally included both tags.
change
*c =(struct student)malloc(sizeof(struct student));
to
c =(struct student*) malloc(sizeof(struct student));

How could these lines of code cause the exact same program to crash sometimes but work fine others?

I have a struct with an int and an array of pointers to structs:
//Define a struct
struct city
{
//Declaration of struct members
int city_num;
struct city **connected;
};
and an array of 'n' of these structs:
struct city* cities;
cities = malloc(n*sizeof(struct city));
and I want to assign a pointer to one struct to the 'connected' member of another struct after allocating space for it.
cities[j].connected = realloc(cities[j].connected, (1*sizeof(struct city*));
cities[i].connected = realloc(cities[i].connected, (1*sizeof(struct city*));
cities[j].connected[0]=&list[i];
cities[i].connected[0]=&list[j];
but the program SOMETIMES crashes at the two last lines. Yesterday it was crashing like it is now, then late at night it just started working like that without me changing anything (I was just commenting the rest of the code) and today after working all morning it just decided to start crashing again a while ago. (I am using Code::Blocks 13.12)
I have put together a very simplified version of the program to show you guys what the problem is.
#include <stdio.h>
#include <stdlib.h>
//Define a struct
struct city
{
//Declaration of struct members
int city_num;
struct city **connected;
};
int main()
{
int n = 2;
struct city* cities;
cities = malloc(n*sizeof(struct city));
cities[0].city_num = 1;
cities[1].city_num = 2;
cities[0].connected = realloc(cities[0].connected, (1*sizeof(struct city*)));
cities[1].connected = realloc(cities[1].connected, (1*sizeof(struct city*)));
//CRASHES AT THESE TWO LINES <-------------------------------------------------
cities[0].connected[0]=&cities[1];
cities[1].connected[0]=&cities[0];
//I have ommitted the memory freeing from this code as the problem is caused above this point
return 0;
}
The first argument to realloc() must be an address that was returned by malloc(), or a previous call to realloc().
The following line:
cities[0].connected = realloc(cities[0].connected, (1*sizeof(struct city*)));
Passes cities[0].connected, which does not contain the address returned by one of these functions. In fact, it hasn't been initialized at all! Therefore, this is an invalid call to realloc().
This is considered undefined behavior, and is subject to crash your code. However, since we have no idea what address you are passing and it is likely a different address each time, then it might sometimes no crash. But it is always wrong.
Note: If you pass NULL as the first argument, then realloc() will work like malloc(). But here you are passing an unitialized value, which could be anything.
You need to do something like this:
cities[0].connected = malloc(1*sizeof(struct city*));
Note that the code to free up this memory just became a bit more complex, as you'll need to free each of these addresses.
realloc() reallocates memory when more is required than was previously allocated by malloc() or calloc().
But it also works when the first parameter passed is NULL.
So to answer your question the reason your code sometimes works and sometimes does not, is because although the pointer passed has not been initialised by a previous allocation, it happens to be sometimes NULL.

C generic linked-list

I have a generic linked-list that holds data of type void* I am trying to populate my list with type struct employee, eventually I would like to destruct the object struct employee as well.
Consider this generic linked-list header file (i have tested it with type char*):
struct accListNode //the nodes of a linked-list for any data type
{
void *data; //generic pointer to any data type
struct accListNode *next; //the next node in the list
};
struct accList //a linked-list consisting of accListNodes
{
struct accListNode *head;
struct accListNode *tail;
int size;
};
void accList_allocate(struct accList *theList); //allocate the accList and set to NULL
void appendToEnd(void *data, struct accList *theList); //append data to the end of the accList
void removeData(void *data, struct accList *theList); //removes data from accList
--------------------------------------------------------------------------------------
Consider the employee structure
struct employee
{
char name[20];
float wageRate;
}
Now consider this sample testcase that will be called from main():
void test2()
{
struct accList secondList;
struct employee *emp = Malloc(sizeof(struct employee));
emp->name = "Dan";
emp->wageRate =.5;
struct employee *emp2 = Malloc(sizeof(struct employee));
emp2->name = "Stan";
emp2->wageRate = .3;
accList_allocate(&secondList);
appendToEnd(emp, &secondList);
appendToEnd(emp2, &secondList);
printf("Employee: %s\n", ((struct employee*)secondList.head->data)->name); //cast to type struct employee
printf("Employee2: %s\n", ((struct employee*)secondList.tail->data)->name);
}
Why does the answer that I posted below solve my problem? I believe it has something to do with pointers and memory allocation. The function Malloc() that i use is a custom malloc that checks for NULL being returned.
Here is a link to my entire generic linked list implementation: https://codereview.stackexchange.com/questions/13007/c-linked-list-implementation
The problem is this accList_allocate() and your use of it.
struct accList secondList;
accList_allocate(&secondList);
In the original test2() secondList is memory on the stack. &secondList is a pointer to that memory. When you call accList_allocate() a copy of the pointer is passed in pointing at the stack memory. Malloc() then returns a chunk of memory and assigns it to the copy of the pointer, not the original secondList.
Coming back out, secondList is still pointing at uninitialised memory on the stack so the call to appendToEnd() fails.
The same happens with the answer except secondList just happens to be free of junk. Possibly by chance, possibly by design of the compiler. Either way it is not something you should rely on.
Either:
struct accList *secondList = NULL;
accList_allocate(&secondList);
And change accList_allocate()
accList_allocate(struct accList **theList) {
*theList = Malloc(sizeof(struct accList));
(*theList)->head = NULL;
(*theList)->tail = NULL;
(*theList)->size = 0;
}
OR
struct accList secondList;
accList_initialise(secondList);
With accList_allocate() changed to accList_initialise() because it does not allocate
accList_initialise(struct accList *theList) {
theList->head = NULL;
theList->tail = NULL;
theList->size = 0;
}
I think that your problem is this:
You've allocated secondList on the stack in your original test2 function.
The stack memory is probably dirty, so secondList requires initialization
Your accList_allocate function takes a pointer to the list, but then overwrites it with the Malloc call. This means that the pointer you passed in is never initialized.
When test2 tries to run, it hits a bad pointer (because the memory isn't initialized).
The reason that it works when you allocate it in main is that your C compiler probably zeros the stack when the program starts. When main allocates a variable on the stack, that allocation is persistent (until the program ends), so secondList is actually, and accidentally, properly initialized when you allocate it in main.
Your current accList_allocate doesn't actually initialize the pointer that's been passed in, and the rest of your code will never see the pointer that it allocates with Malloc. To solve your problem, I would create a new function: accList_initialize whose only job is to initialize the list:
void accList_initialize(struct accList* theList)
{
// NO malloc
theList->head = NULL;
theList->tail = NULL;
theList->size = 0;
}
Use this, instead of accList_allocate in your original test2 function. If you really want to allocate the list on the heap, then you should do so (and not mix it with a struct allocated on the stack). Have accList_allocate return a pointer to the allocated structure:
struct accList* accList_allocate(void)
{
struct accList* theList = Malloc( sizeof(struct accList) );
accList_initialize(theList);
return theList;
}
Two things I see wrong here based on the original code, in the above question,
What you've seen is undefined behaviour and arose from that is the bus error message as you were assigning a string literal to the variable, when in fact you should have been using the strcpy function, you've edited your original code accordinly so.. something to keep in mind in the future :)
The usage of the word Malloc is going to cause confusion, especially in peer-review, the reviewers are going to have a brain fart and say "whoa, what's this, should that not be malloc?" and very likely raise it up. (Basically, do not call custom functions that have similar sounding names as the C standard library functions)
You're not checking for the NULL, what if your souped up version of Malloc failed then emp is going to be NULL! Always check it no matter how trivial or your thinking is "Ah sher the platform has heaps of memory on it, 4GB RAM no problem, will not bother to check for NULL"
Have a look at this question posted elsewhere to explain what is a bus error.
Edit: Using linked list structures, in how the parameters in the function is called is crucial to the understanding of it. Notice the usage of &, meaning take the address of the variable that points to the linked list structure, and passing it by reference, not passing by value which is a copy of the variable. This same rule applies to usage of pointers also in general :)
You've got the parameters slightly out of place in the first code in your question, if you were using double-pointers in the parameter list then yes, using &secondList would have worked.
It may depend on how your Employee structure is designed, but you should note that
strcpy(emp->name, "Dan");
and
emp->name = "Dan";
function differently. In particular, the latter is a likely source of bus errors because you generally cannot write to string literals in this way. Especially if your code has something like
name = "NONE"
or the like.
EDIT: Okay, so with the design of the employee struct, the problem is this:
You can't assign to arrays. The C Standard includes a list of modifiable lvalues and arrays are not one of them.
char name[20];
name = "JAMES" //illegal
strcpy is fine - it just goes to the memory address dereferenced by name[0] and copies "JAMES\0" into the memory there, one byte at a time.

Struct memory allocation fault

I am writing a C project with pointers and structs, and right now facing this problem:
There is a structure
struct Customer
{
char Name[80];
char Address[40];
int ID;
int Pnumber;
};
and I am gonna make a dynamic array of this structs with *line_count* number of members. I use this code, but it crashes a program:
struct Customer* ph;
ph = (struct Customer*)malloc(line_count * sizeof(struct Customer));
What am I doing wrong?
Good:
struct Customer* ph;
ph = (struct Customer*)malloc(line_count * sizeof(struct Customer));
Better:
struct Customer* ph =
(struct Customer*)malloc(line_count * sizeof(struct Customer));
if (!ph) {
<<error handling>>
...
But frankly, it sounds like the problem is elsewhere in your code.
There's nothing fundamentally wrong with your malloc().
Maybe "line_count" is bogus, maybe "malloc()" is failing (in which case, it should return "NULL") ... or maybe you're accessing the struct incorrectly and/or failing to initialize it correctly.
A stack traceback of the actual crash would be very useful.
The piece of code you are showing might crash only if ph == NULL after the malloc call and you dereference it.
From the malloc man page:
The malloc() and calloc() functions return a pointer to the allocated
memory that is suitably aligned for any kind of variable. On error,
these functions return NULL. NULL may also be returned by a
successful call to malloc() with a size of zero, or by a successful
call to calloc() with nmemb or size equal to zero.

Resources