double linked list in c send data from function - c

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.

Related

Cannot figure out how to free my structure

I need to free() all the memory allocated for my structure config.
struct keysnvalues {
char* key;
char* value;
};
struct section {
char *name;
struct keysnvalues *keysnvalues;
int keysnvalues_ammount;
};
struct config {
struct section *sections;
int section_ammount;
};
In the beggining of the code I do this
struct section * sect = malloc(sizeof(struct section) * 255);
struct keysnvalues * keysnvalue = malloc(sizeof(struct keysnvalues) * 255);
If I want to add section I do this for the first one
sect[++num_section].name = buffer; // buffer is the name
And for the next sections
sect[num_section].keysnvalues = keysnvalue;
sect[num_section].keysnvalues_ammount = num_keysnvalues;
cfg -> section_ammount++;
//start with new keysnvalue
num_keysnvalues = 0;
keysnvalue = malloc(sizeof(struct keysnvalues) * 255);
sect[++num_section].name = buffer;
sect[num_section].keysnvalues = 0;
If I want to add a key and a value to section I am working with I do this
keysnvalue[num_keysnvalues].key = key;
keysnvalue[num_keysnvalues++].value = value;
The whole code is here: https://pastebin.com/pGztJ9k4
I am aware of the fact that this is probably a stupid question, but I could not figure out how to free the whole structure config for hours now.
I would really appreciate your help.
Generally, you should free() a pointer if and only if it has been allocated through malloc(). To achieve this, you have to make sure not to "loose" any pointer to a malloced memory address, e.g. by assigning malloc several times to the same variable without having copied it's previous value or without having freed the previously assigned memory.
I did not analyse the complete code you referred to.
But it seems as if you copy the value of keysnvalue to the current section before mallocing a new value for sect[i].keysnvalues.
Hence, it seems that each section get's its own keysnvalue, and you can loop it through:
for (int i=0;i< num_section;i++) {
if (sect[i].keysnvalues != NULL) {
free(sect[i].keysnvalues);
// free(sect[i].name); // if buffer has also been malloced
}
}
free (keysnvalue);
free (sect);
It may be that you also have to loop trough each sect[i].keysnvalue in order to eventually free key/value.
Make sure that section members that you are going to free at the end of the program are always initialised either with NULL or a malloced value in order to prevent your code from "freeing" a garbage pointer value.
When you reset 'keysnvalue' with the next 'malloc()', you are overwriting the pointer to the previous value of 'keysnvalue'. That leaves the associated storage unreachable, i.e a 'memory leak' [unless you maintain a copy of the previous value of 'keysnvalue' in another location]. If you are really replacing the structure with a fresh one, you must 'free()' the old one first, AND THEN 'malloc()' the next one - you cannot wait until the end to clean up everything.
Personally I wouldn't do it that way - for a fresh structure, I would call 'memset()' to zero out the existing structure.

function definition in C

I can't get that why are we using a * in a function declaration like:
struct node *create_ll(struct node *)
{
body here
}
Why do we use that * before create_ll which is the function name?
And it is called using the statement:
start = create_ll(start);
If this could help.
Please explain this.
struct node *create_ll(struct node *)
means the return type of this function will be a pointer of type struct node. read it like
struct node * ,
not like
*create_ll.
This has nothing to do with the NAME of the function.
As stated by Sourav (thought I'd elaborate further, and I can't comment due to low rep), using the * operator returns a pointer to the given type, this pointer is actually just a number that stores the starting memory address of the given object (the actual type of number depends on OS and processor... 32bit numbers on a 32bit OS/processor, 64bit numbers on a 64bit OS/processor) and not the actual object itself.
For instance: even if you have a 64bit processor, if you're running Windows XP (32bit) then the resulting number will be a 32bit number (4 bytes of memory to store), if you switched over to a 64bit OS then the resulting number would be a 64bit number (8 bytes of memory to store).
In order to get a pointer in the first place, the & operator is needed... unless dynamically allocated using malloc() or something similar.
When actually using the pointer, then the -> operator is used (instead of using the . operator).
To give an example in code:
struct test_object
{
unsigned int value;
};
void function()
{
// Declare a POINTER to an object of type <test_object>
test_object *pointer;
// Declare 2 temporary objects
test_object object1, object2;
// Set object1's value using the . operator
object1.value = 1;
// Set object2's value using the . operator
object2.value = 2;
// Set the pointer to point at object2
// Note the usage of the & operator
pointer = &object2;
// Print out whatever the pointer points to (in this case object2)
// Note the usage of -> instead of .
// This is how pointers access the object being pointed at
cout << pointer->value;
// Now set the pointer to point at object1
pointer = &object1;
// Print out whatever the pointer points to (in this case object1)
// Note this is the EXACT same line used above
// but the end result is completely different
cout << pointer->value;
};
A word of warning, pointers can be quite dangerous if used incorrectly. In the above example, I didn't initialize the pointer when I declared it...
IE:
test_object *pointer = NULL;
If you tried to use the COUT line in the above code without setting the pointer first, then really bad stuff can happen (program crashes, accessing the wrong memory location giving unexpected results, etc).
The best way to avoid such things is to ALWAYS initialize pointers to NULL, and ALWAYS check if the pointer is NULL before actually trying to access the memory being pointed to...
Re-using the above code, but making it safer:
void function()
{
// Declare the pointer
test_object *pointer = NULL;
// Declare the 2 actual objects
test_object object1, object2;
// Set values
object1.value = 1;
object2.value = 2;
// Check if pointer isn't pointing at anything
if (pointer == NULL)
{
// At this moment in time, it doesn't point at anything (it's still NULL)
// So this code WON'T run, which stops the program crashing
// Print out whatever the pointer points to
cout << pointer->value;
}
// Set the pointer to point at object2
pointer = &object2;
// Check if pointer isn't pointing at anything
if (pointer == NULL)
{
// Now it DOES point to something (anything other than NULL)
// Print out whatever the pointer points to
cout << pointer->value;
}
};
If you comment out the 2 if statements, then the program will probably crash when the first COUT is reached (it SHOULD crash, but not always).
I hope this answers your question
Here * means you are using pointers.Reason is that since Node could contain lot of variables and it would consume lot of memory So to avoid this we use pointers like
struct Node*
Since in this case when calling function and passing argument or returning argument of type Node you save lot of memory since in pointers only the address of the Node is passed or returned.Otherwise huge copy(If Node have lot of variables) of the Node will be made in memory before passing to or returning from the functions.
It is just like if I take you to an apple store and go with you to buy them and in the pointer case I tell you only the address of the shop and you buy yourself.
Now coming to second part of your question struct Node*
here function will return pointer of type struct Node so to use this you will write following code.
struct Node* someInput;
sturct Node* someOutput=create_ll(someInput);
and to use members inside someOutput for example if there are members like name and age inside Node you will do following
someOutput->age;
someOutput->name;
Your function is returning a pointer.
In this case it is returning a pointer of type struct node.
so the function prototype looks like
struct node *func(struct node *);

Assigning value to ptr in struct (C)

I have declared a structure in my .h file, as such:
struct node{
char* string;
}
I intend this to have created a structure, example, with one member, a character pointer named string.
Now, I figure out how long the string is and malloc an array of appropriate size, taking the input with that.
char* test;
test = (char*) malloc( n * sizeof(char) );
Insofar as I am aware, this has created character pointer test, and has assigned it to point at the head of the array I just malloc'd. I then proceed to assign each array slot to a character that the user has entered, and I read it back out - this all compiles and works appropriately. My problem comes when I try to assign this character pointer to the character pointer in a structure node passed in to this structure, as:
int f1( struct node* new ){
So I try to assign the pointer in the structure to the value of the pointer to the array, like so:
new->string = test;
But I segfault.
To me, this seems like I am assigning a char* to something that expects a char* so this should be working fine...I'm probably missing something stupid, but does anyone have a direction to point me in? Thanks much!
Check your caller of f1() and make sure your parameter is valid.
This will work:
struct node *you = malloc(sizeof(struct node));
if (you)
{
f1(you);
free(you);
}
As will this:
struct node me;
f1(&me);
This will NOT work
struct node *me;
int f1(me);
Some observations to note:
sizeof(char) is one by definition.
Recommended way of calling malloc is one that avoids casts as well as gets sizeof to infer the type from the pointer being allocated. (See below)
Avoid using names such as new for your identifiers (to the extent possible).
Remember to free the string member within node when you are done.
To elaborate #2, see below --
struct MyType *foo;
foo = malloc( n * sizeof *foo ); /* allocate n elements where n > 0 */
For some reason, if you chose foo to be of some other type, the malloc call is one less line for you to worry about. Also, should you forget to include stdlib.h, the compiler will let you know about it.

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.

help with structs and looping in C

beginner in C here. Is this legal here? I keep getting status access violation when i run this code:
struct point {
char *x;
char *y;
}
int main()
{
....
struct point *pt;
for (;;)
{
....
pt = process_message(message);
printf("%s",pt->x);
...
}
}
struct point* process_message(char* message)
{
struct point *pt;
pt = malloc(1*sizeof(struct point))
strncpy(pt->x, message, 4);
return pt;
}
EDIT
Hi guys i made some changes...but still getting the access violation. pls advise!
You need to allocate memory for struct point in process_message.
Something like this:
struct point* process_message(char* message)
{
struct point *pt;
pt = malloc(1*sizeof(struct point));
// ... do some processing ...
return pt;
}
Of course, you should free the pointer at some point afterwards.
Also you should return a struct point in process_message or check your type concordance. If you look carefully, you will see you are returning a struct price* but you are expecting (on the calling side) a struct point *.
UPDATE:
Now that question was updated, you will also need to allocate memory for char *x and char *y if you want to do this:
strncpy(pt->x, message, 4);
I would recommend to read a little bit (or a lot) about memory management and pointers in C++. Pointers are not the only way of dealing with data in C Programming Language.
(NO ERROR CHECKING DONE FOR CODE SIMPLICITY)
Your main function is OK. Your problem is in process_message, where you're using a pointer-to-a-struct but not allocating any memory for it, accessing it, then returning it. Declaring a pointer alone does not create the memory to hold the struct. So you should allocate (use malloc for example) the memory for the struct, so that the memory will "exist" after the end of the function. Then you can return the pointer to it as you're doing, and then you would free it in main when you were done with it.
There are possibly better ways to accomplish the goal here given the simple operation you're doing. One is to keep one "scratch" struct local in your main function, and pass its address to process message:
struct point pt;
process_message(message, &pt);
printf("%s", pt.x);
This will "Reuse" the local memory and not require the alloc/free. Notice here that you don't return anything, you just "fill in" the struct in the process function.
Finally, if you're using a modern version of C, you can actually just return the full structure from the function if you want:
struct point process_message(char* message)
{
struct point pt;
... do some processing ...
return pt;
}
And call it like this:
struct point pt = process_message(message);
Remember to allocate memory in the function process_message
pt = malloc (sizeof (struct point));
/* do processing */
return pt;
also after you have finished working with pt remember to free it free (pt).
EDIT
Also you need to allocate the memory blocks to store the strings to x and y in the function, after allocation of the pt. When you have done working, you need to free the strings first (memory blocks) and then the structure.
Whenever you create pointer, it's just a sizeof(ptr) memory , which points to some data. So you must have some memory where your data is stored.
So either allocate memory in your function ( process_message), or in calling function.
it should go like
struct point *pt = (struct point*)malloc(sizeof(struct point));
As written now, you're allocating the struct point, but that structure contains pointers to strings, and not storage for the strings themselves. You need to allocate space for the strings before you copy into them:
pt = malloc(1*sizeof(struct point));
pt->x = (char *)malloc( strlen(message) + 1);
Don't forget to do the same for pt->y before you use it, and don't forget to separately free the storage allocated for the strings, and then that allocated for the struct.

Resources