Recursive Solution to Free Memory in C - c

I am working on building a shell and have this function that frees memory of the programs in the command line. I am interested in trying to create a recursive solution as I am trying to better understand recursion.
The program struct in the header file looks like this and is implemented as a linked list so it can support pipes.
// The program to be executed
typedef struct prog {
arglist_t args; // Arguments, including the program name
redirection_t redirection; // Optional redirections
struct prog *prev; // The prev program in the pipeline, if any; NULL otherwise
} prog_t;
This is the iterative free memory function implementation:
void free_memory(prog_t *exe) {
prog_t *tmp;
while(exe != NULL) {
for (int i = 0; i < exe->args.size; i++) {
if(exe->args.args[i]) free(exe->args.args[i]);
}
free(exe->args.args);
if (exe->redirection.in) free(exe->redirection.in);
if (exe->redirection.out1) free(exe->redirection.out1);
if (exe->redirection.out2) free(exe->redirection.out2);
if(exe->redirection.in != NULL) {
free(exe->redirection.in);
}
if(exe->redirection.out1 != NULL) {
free(exe->redirection.out1);
}
if(exe->redirection.out2 != NULL) {
free(exe->redirection.out2);
}
tmp = exe;
exe = exe->prev;
free(tmp);
}
}
How would I go about developing a recursive solution?

For recursion, you call instead of looping. For your case, change the while into an if and change the last three lines of the while/if body to
free_memory(exe->prev);
free(exe);
or to make it more efficient (tail recursive):
tmp = exe->prev;
free(exe);
free_memory(tmp);
the tail recursive version will probably generate identical code to your while loop.

Related

How do I send the linked list as a function argument

<DBDLinkedList.h>
...
typedef struct _dbDLinkedList
{
Node * head;
Node * tail;
Node * cur;
int numOfData;
} DBDLinkedList;
typedef DBDLinkedList List;
...
<mysourcecode.c>
int main(void)
{
...
List list;
int data;
ListInit(&list);
for(i=0; i<ID_LEN; i++)
LInsert(&list, new_id[i]);
solution(list, data);
...
}
int solution(List list, int data)
{
...
if(LFirst(&list, &data))
{
int i=1;
if(data==46)
LRemove(&list);
i++;
while(LNext(&list, &data))
{
if(i==numOfData)
if(data==46)
LRemove(&list);
i++;
}
}
...
}
I used dummy node doubly linked list.
When I complied this project, error occurred :
‘numOfData’ undeclared (first use in this function).
I'm not used to using Linked list.
How do I send the linked list as a function argument(for solution())?
from what I could see, the problem might not be in sending the linked list as a function argument. In "if(i==numOfData)", you are trying to access the numOfData, which is a part of a 'List' structure, so you need to access it through 'List' variable.... Perhaps replacing that line of code with something like "if(i == list.numOfData)" will do the trick
numOfData is not a variable. You most probably intended to access the current node's numOfData member.
But you really don't need to access that member directly. It seems likely (without seeing the code) that LNext will put that value in your data variable -- it is the reason why you pass &data as argument to LNext.
This brings us to another issue in your code. You call solution with data, but you never gave data a value. If the intention is to remove the node with value 46, then the main program should call solution as follows:
solution(list, 46);
And solution should be implemented as follows:
int solution(List list, int dataToRemove) {
if (!LFirst(&list, &data)) {
return 0; // to indicate that value to delete was not found
}
while (data != dataToRemove) {
if (!LNext(&list, &data)) {
return 0; // to indicate that value to delete was not found
}
}
LRemove(&list);
return 1; // to indicate success
}

How to handle malloc failing and returning NULL?

I'm a bit confused on how to check if a memory allocation failed in order to prevent any undefined behaviours caused by a dereferenced NULL pointer.
I know that malloc (and similiar functions) can fail and return NULL, and that for this reason the address returned should always be checked before proceeding with the rest of the program. What I don't get is what's the best way to handle these kind of cases. In other words: what is a program supposed to do when a malloc call returns NULL?
I was working on this implementation of a doubly linked list when this doubt raised.
struct ListNode {
struct ListNode* previous;
struct ListNode* next;
void* object;
};
struct ListNode* newListNode(void* object) {
struct ListNode* self = malloc(sizeof(*self));
if(self != NULL) {
self->next = NULL;
self->previous = NULL;
self->object = object;
}
return self;
}
The initialization of a node happens only if its pointer was correctly allocated. If this didn't happen, this constructor function returns NULL.
I've also written a function that creates a new node (calling the newListNode function) starting from an already existing node and then returns it.
struct ListNode* createNextNode(struct ListNode* self, void* object) {
struct ListNode* newNext = newListNode(object);
if(newNext != NULL) {
newNext->previous = self;
struct ListNode* oldNext = self->next;
self->next = newNext;
if(oldNext != NULL) {
newNext->next = oldNext;
oldNext->previous = self->next;
}
}
return newNext;
}
If newListNode returns NULL, createNextNode as well returns NULL and the node passed to the function doesn't get touched.
Then the ListNode struct is used to implement the actual linked list.
struct LinkedList {
struct ListNode* first;
struct ListNode* last;
unsigned int length;
};
_Bool addToLinkedList(struct LinkedList* self, void* object) {
struct ListNode* newNode;
if(self->length == 0) {
newNode = newListNode(object);
self->first = newNode;
}
else {
newNode = createNextNode(self->last, object);
}
if(newNode != NULL) {
self->last = newNode;
self->length++;
}
return newNode != NULL;
}
if the creation of a new node fails, the addToLinkedList function returns 0 and the linked list itself is left untouched.
Finally, let's consider this last function which adds all the elements of a linked list to another linked list.
void addAllToLinkedList(struct LinkedList* self, const struct LinkedList* other) {
struct ListNode* node = other->first;
while(node != NULL) {
addToLinkedList(self, node->object);
node = node->next;
}
}
How should I handle the possibility that addToLinkedList might return 0? For what I've gathered, malloc fails when its no longer possible to allocate memory, so I assume that subsequent calls after an allocation failure would fail as well, am I right? So, if 0 is returned, should the loop immediately stop since it won't be possible to add any new elements to the list anyway?
Also, is it correct to stack all of these checks one over another the way I did it? Isn't it redundant? Would it be wrong to just immediately terminate the program as soon as malloc fails? I read that it would be problematic for multi-threaded programs and also that in some istances a program might be able to continue to run without any further allocation of memory, so it would be wrong to treat this as a fatal error in any possible case. Is this right?
Sorry for the really long post and thank you for your help!
It depends on the broader circumstances. For some programs, simply aborting is the right thing to do.
For some applications, the right thing to do is to shrink caches and try the malloc again. For some multithreaded programs, just waiting (to give other threads a chance to free memory) and retrying will work.
For applications that need to be highly reliable, you need an application level solution. One solution that I've used and battle tested is this:
Have an emergency pool of memory allocated at startup.
If malloc fails, free some of the emergency pool.
For calls that can't sanely handle a NULL response, sleep and retry.
Have a service thread that tries to refill the emergency pool.
Have code that uses caching respond to a non-full emergency pool by reducing memory consumption.
If you have the ability to shed load, for example, by shifting load to other instances, do so if the emergency pool isn't full.
For discretionary actions that require allocating a lot of memory, check the level of the emergency pool and don't do the action if it's not full or close to it.
If the emergency pool gets empty, abort.
How to handle malloc failing and returning NULL?
Consider if the code is a set of helper functions/library or application.
The decision to terminate is best handled by higher level code.
Example: Aside from exit(), abort() and friends, the Standard C library does not exit.
Likewise returning error codes/values is a reasonable solution for OP's low-level function sets too. Even for addAllToLinkedList(), I'd consider propagating the error in the return code. (Non-zero is some error.)
// void addAllToLinkedList(struct LinkedList* self, const struct LinkedList* other) {
int addAllToLinkedList(struct LinkedList* self, const struct LinkedList* other) {
...
if (addToLinkedList(self, node->object) == NULL) {
// Do some house-keepeing (undo prior allocations)
return -1;
}
For the higher level application, follow your design. For now, it may be a simple enough to exit with a failure message.
if (addAllToLinkedList(self, ptrs)) {
fprintf(stderr, "Linked List failure in %s %u\n", __func__, __LINE__);
exit(EXIT_FAILURE);
}
Example of not exiting:
Consider a routine that read a file into a data structure with many uses of LinkedList and the file was somehow corrupted leading to excessive memory allocations. Code may want to simply free everything for that file (but just for that file), and simply report to the user "invalid file/out-of-memory" - and continue running.
if (addAllToLinkedList(self, ptrs)) {
free_file_to_struct_resouces(handle);
return oops;
}
...
return success;
Take away
Low level routines indicate an error somehow. Higher level routines can exit code if desired.

Whether code is read from top to bottom

I am creating a program in c which is based on a linked list, where every node (of struct) holds an integer and a pointer to the next node.
I use dynamic allocation (malloc) and deallocation (free) as new nodes are added and old nodes are deleted.
when a node is deleted a function named delete is called.
I discovered that the program crashes sometimes when this delete-function is called and I KNOW that its something with the pointers in the method but I dont know WHERE in the code (row number) and WHY this happends.
I am used to high-level languages such as Java and I am used to encircle the problem by putting print-syntax at certain places in the method just to reveal WHERE it crashes.
I thought I could do the same with c and with pointer because to my knowledge I beleive the code is read from top to bottom that is 1, 2, 3, 4, and so on. (maybe interrupt handlers behave another way?)
So in this function named delete I have gone so far by putting this printf() at the very beginning of the delete-function - and all the same the program crashes.
So my Question - is it really possible that its some syntax in the delete-function (when I loop pointers for instance) that causes the crash WHEN not even the printf() is printing?
Am I wrong when I believe that the program is executed from to to bottom - that is 1, 2, 3 ....
You can se my printf-function in the very beginning of delete-function
And by the way - how could I solve this problem when I get this cryptic crash message from windows? See the bitmap!!
Greatful for answers!!!
int delete(int data) {
printf("IN THE BEGINNING OF DELETE!!!");
int result = 0;
if (queueref.last != NULL) {
node *curr_ptr;
node *prev_ptr;
node *temp_ptr;
if (queueref.first->data == data) {
temp_ptr = queueref.first;
queueref.first = queueref.first->next;
destroy_node(temp_ptr);
result = 1;
if (queueref.first == NULL) {
queueref.last = NULL;
puts("queue is now empty!!!");
}
} else {
prev_ptr = queueref.first;
curr_ptr = queueref.first->next;
printf("prev_ptr: %d\n", prev_ptr);
printf("curr_ptr: %d\n", curr_ptr);
while(curr_ptr != NULL) {
if (curr_ptr->data == data) {
result = 1;
if (curr_ptr->next != NULL) {
temp_ptr = curr_ptr;
destroy_node(temp_ptr);
prev_ptr->next = curr_ptr->next;
} else {
temp_ptr = curr_ptr;
queueref.last = prev_ptr;
prev_ptr->next = NULL;
destroy_node(temp_ptr);
}
}
curr_ptr = curr_ptr->next;
prev_ptr = prev_ptr->next;
}
}
}
return result;
}
Common mistake, here's the deal. This
printf("IN THE BEGINNING OF DELETE!!!");
needs to be
printf("IN THE BEGINNING OF DELETE!!!\n");
^^ note the newline
The reason is because stdio does not flush stdout until it sees a newline. If you add that newline, you should see the printf when the code enters the function. Without it, the program could crash, the stdout buffer would not have been flushed and would not see the printf.
Your code seems to have lots of implementation flaws. As a general advice I would recommend using some standard well-tested queue support library and static code analyzers (in this case you would even find dynamic analyzer valgrind very helpful, I guess).
For example, if implementation of destroy_node(ptr) is equivalent to free(ptr), then your code suffers from referencing destroyed data (or ,in other words, garbage) in this code snippet:
while(curr_ptr != NULL) {
if (curr_ptr->data == data) {
result = 1;
if (curr_ptr->next != NULL) {
temp_ptr = curr_ptr;
destroy_node(temp_ptr);
prev_ptr->next = curr_ptr->next; //<- curr_ptr is still in stack
//or register, but curr->next
//is garbage
// what if curr_ptr is first node? did you forget to update queueref.first?
} else {
temp_ptr = curr_ptr;
queueref.last = prev_ptr;
prev_ptr->next = NULL;
destroy_node(temp_ptr);
}
// if you you need to destroy only one node - you can leave the loop here with break;
}
curr_ptr = curr_ptr->next; /// assigning garbage again if node is found
prev_ptr = prev_ptr->next;
The reason why using destroyed data can work in * most * (if I can say that, basically this is unpredictable) cases is that the chances that this memory can be reused by other part of program for dynamically allocated data can vary on timings and code flow.
PS
Regarding cryptic messages in the Windows box - when program crashes OS basically generates crashdump and prints registers (and dumps some relevant memory parts). Registers and memory dumps can show the place of crash and immediate register/stack values but you have to now memory map and assembler output to understand it. Crashdump can be loaded to debugger (WinDbg) together with unstripped binary to check stactrace and values of local variables at the moment of crash. All these I described very very briefly, you could find tons of books / guides searching for "windows crash or crashdump analysis"

C standard binary trees

I'm pretty much of a noob in regards to C programming.
Been trying for a few days to create a binary tree from expressions of the form:
A(B,C(D,$))
Where each letters are nodes.
'(' goes down a level in my tree (to the right).
',' goes to the left-side branch of my tree
'$' inserts a NULL node.
')' means going up a level.
This is what I came up with after 2-3 days of coding:
#define SUCCESS 0
typedef struct BinaryTree
{
char info;
BinaryTree *left,*right,*father;
}BinaryTree;
int create(BinaryTree*nodeBT, const char *expression)
{
nodeBT *aux;
nodeBT *root;
nodeBT *parent;
nodeBT=(BinaryTree*) malloc (sizeof(BinaryTree));
nodeBT->info=*expression;
nodeBT->right=nodeBT->left=NULL;
nodeBT->father = NULL;
++expression;
parent=nodeBT;
root=nodeBT;
while (*expression)
{if (isalpha (*expression))
{aux=(BinaryTree*) malloc (sizeof(BinaryTree));
aux->info=*expression;
aux->dr=nodeBT->st=NULL;
aux->father= parent;
nodeBT=aux;}
if (*expression== '(')
{parent=nodeBT;
nodeBT=nodeBT->dr;}
if (*expression== ',')
{nodeBT=nodeBT->father;
nodeBT=nodeBT->dr;}
if (*expression== ')')
{nodeBT=nodeBT->father;
parent= nodeBT->nodeBT;}
if (*expression== '$')
++expression;
++expression;
}
nodeBT=root;
return SUCCESS;
}
At the end, while trying to access the newly created tree, I keep getting "memory unreadable 0xCCCCCC". And I haven't got the slightest hint where I'm getting it wrong.
Any idea ?
Several problems:
You haven't shown us the definition of type nodeBT, but you've declared aux, root, and parent to be pointers to that type.
You then assign aux to point to a BinaryTree even though it's declared to point to a nodeBT.
You assign to aux->dr, which isn't part of BinaryTree, so I can't just assume you typed nodeBT where you meant BinaryTree. You assign to nodeBT->st, that is not a part of BinaryTree either.
You try to return the parsed tree by assigning nodeBT=root. The problem is that C is a “call-by-value” language. This implies that when your create function assigns to nodeBT, it is only changing its local variable's value. The caller of create doesn't see that change. So the caller doesn't receive the root node. That's probably why you're getting your “memory unreadable” error; the caller is accessing some random memory, not the memory containing the root node.
Your code will actually be much easier to understand if you write your parser using a standard technique called “recursive descent”. Here's how.
Let's write a function that parses one node from the expression string. Naively, it should have a signature like this:
BinaryTree *nodeFromExpression(char const *expression) {
To parse a node, we first need to get the node's info:
char info = expression[0];
Next, we need to see if the node should have children.
BinaryTree *leftChild = NULL;
BinaryTree *rightChild = NULL;
if (expression[1] == '(') {
If it should have children, we need to parse them. This is where we put the “recursive” in “recursive descent”: we just call nodeFromExpression again to parse each child. To parse the left child, we need to skip the first two characters in expression, since those were the info and the ( of the current node:
leftChild = nodeFromExpression(expression + 2);
But how much do we skip to parse the right child? We need to skip all the characters that we used while parsing the left child…
rightChild = nodeFromExpression(expression + ???
We don't know how many characters that was! It turns out we need to make nodeFromExpression return not just the node it parsed, but also some indication of how many characters it consumed. So we need to change the signature of nodeFromExpression to allow that. And what if we run into an error while parsing? Let's define a structure that nodeFromExpression can use to return the node it parsed, the number of characters it consumed, and the error it encountered (if there was one):
typedef struct {
BinaryTree *node;
char const *error;
int offset;
} ParseResult;
We'll say that if error is non-null, then node is null and offset is the offset in the string where we found the error. Otherwise, offset is just past the last character consumed to parse node.
So, starting over, we'll make nodeFromExpression return a ParseResult. It will take the entire expression string as input, and it will take the offset in that string at which to start parsing:
ParseResult nodeFromExpression(char const *expression, int offset) {
Now that we have a way to report errors, let's do some error checking:
if (!expression[offset]) {
return (ParseResult){
.error = "end of string where info expected",
.offset = offset
};
}
char info = expression[offset++];
I didn't mention this the first time through, but we should handle your $ token for NULL here:
if (info == '$') {
return (ParseResult){
.node = NULL,
.offset = offset
};
}
Now we can get back to parsing the children.
BinaryTree *leftChild = NULL;
BinaryTree *rightChild = NULL;
if (expression[offset] == '(') {
So, to parse the left child, we just call ourselves recursively again. If the recursive call gets an error, we return the same result:
ParseResult leftResult = nodeFromExpression(expression, offset);
if (leftResult->error)
return leftResult;
OK, we parsed the left child successfully. Now we need to check for, and consume, the comma between the children:
offset = leftResult.offset;
if (expression[offset] != ',') {
return (ParseResult){
.error = "comma expected",
.offset = offset
};
}
++offset;
Now we can recursively call nodeFromExpression to parse the right child:
ParseResult rightResult = nodeFromExpression(expression, offset);
The error case now is a bit more complex if we don't want to leak memory. We need to free the left child before returning the error:
if (rightResult.error) {
free(leftResult.node);
return rightResult;
}
Note that free does nothing if you pass it NULL, so we don't need to check for that explicitly.
Now we need to check for, and consume, the ) after the children:
offset = rightResult.offset;
if (expression[offset] != ')') {
free(leftResult.node);
free(rightResult.node);
return (ParseResult){
.error = "right parenthesis expected",
.offset = offset
};
}
++offset;
We need to set our local leftChild and rightChild variables while the leftResult and rightResult variables are still in scope:
leftChild = leftResult.node;
rightChild = rightResult.node;
}
We've parsed both children, if we needed to, so now we're ready to construct the node we need to return:
BinaryTree *node = (BinaryTree *)calloc(1, sizeof *node);
node->info = info;
node->left = leftChild;
node->right = rightChild;
We have one last thing to do: we need to set the father pointers of the children:
if (leftChild) {
leftChild->father = node;
}
if (rightChild) {
rightChild->father = node;
}
Finally, we can return a successful ParseResult:
return (ParseResult){
.node = node,
.offset = offset
};
}
I've put all the code in this gist for easy copy'n'paste.
UPDATE
If your compiler doesn't like the (ParseResult){ ... } syntax, you should look for a better compiler. That syntax has been standard since 1999 (§6.5.2.5 Compound Literals). While you're looking for a better compiler, you can work around it like this.
First, add two static functions:
static ParseResult ParseResultMakeWithNode(BinaryTree *node, int offset) {
ParseResult result;
memset(&result, 0, sizeof result);
result.node = node;
result.offset = offset;
return result;
}
static ParseResult ParseResultMakeWithError(char const *error, int offset) {
ParseResult result;
memset(&result, 0, sizeof result);
result.error = error;
result.offset = offset;
return result;
}
Then, replace the problematic syntax with calls to these functions. Examples:
if (!expression[offset]) {
return ParseResultMakeWithError("end of string where info expected",
offset);
}
if (info == '$') {
return ParseResultMakeWithNode(NULL, offset);
}

How to use free on a handle inside a list?-> C -> windows API

I have a list in C that is something like this:
typedef struct _node
{
int number;
DWORD threadID;
HANDLE threadH;
struct *_node next;
} *node;
And you have somthing like this:
node new_node = malloc(sizeof(node));
As you may have guessed out, this list will store information for threads, including their handlers and Id's. Still I am having trouble when I try to do this:
free(new_node);
Everytime I try to do this I encounter an unexpected error, VS saying that there was a data corruption. I've pinned down as much as possible and I found that the problem resides when I try to use free the handle.
I've searched on MSDN how to do this but the only thing I can find is the function that closes the thread (which is not intended here, since I want the thread to run, just deleting it's record from the list).
The question is: how I am supposed to free an handle from the memory? (Considering that this is only a copy of the value of the handle, the active handle is not being deleted).
EDIT: This is the function to insert nodes from the list:
int insereVisitanteLista(node* lista, DWORD threadID, HANDLE threadH, int num_visitante)
{
node visitanteAnterior;
node novoVisitante = (node)malloc(sizeof(node));
if(novoVisitante == NULL)
return 0;
novoVisitante->threadID = threadID;
novoVisitante->threadH = threadH;
novoVisitante->number = num_visitante;
novoVisitante->next = NULL;
if(*lista == NULL)
{
*lista = novoVisitante;
return 1;
}
visitanteAnterior = *lista;
while(visitanteAnterior->next != NULL)
visitanteAnterior = visitanteAnterior->next;
visitanteAnterior->next =novoVisitante;
return 1;
}
And this is the function to delete nodes:
int removeVisitanteLista(node * lista, DWORD threadID)
{
node visitanteAnterior = NULL, visitanteActual;
if(*lista == NULL)
return 0;
visitanteActual = *lista;
if((*lista)->threadID == threadID)
{
*lista = visitanteActual->next;
visitanteActual->next = NULL;
free(visitanteActual);
return 1;
}
while(visitanteActual != NULL && visitanteActual->threadID != threadID)
{
visitanteAnterior = visitanteActual;
visitanteActual = visitanteActual->next;
}
if (visitanteActual == NULL)
return 0;
visitanteAnterior->next = visitanteActual->next;
free(visitanteActual);
return 1;
}
What exactly is a node that you are trying to free? Is this a pointer to a struct _node? If yes, have you allocated it previously? If no, free is not needed, otherwise you have to check if node is not NULL and make sure you do not free it multiple times. It is hard to guess what you are doing and where is an error without a minimal working example reproducing the problem. The only thing I can suggest is to read about memory management in C. This resource might help.
UPDATE:
node in your code is a pointer to _node. So sizeof (node) is a size of a pointer, which is either 4 or 8 bytes (depending on architecture). So you allocate 8 bytes, for example, but assume you have a pointer to the structure which is much larger. As a result, you corrupt memory, and behavior of the program becomes undefined. So changing node novoVisitante = (node)malloc(sizeof(node)) to node novoVisitante = (node)malloc(sizeof(_node)) should fix the problem.
You haven't shown us the context of your call to free() so I need to speculate a little but my first concern is that you didn't mention removing the node from the list before deleting it.
Start by unlinking the node by modifying the next field of the previous (or head) node. If you still get the error, then you have corrupted memory somehow by writing past the end of one of your allocated memory structures or something similar.
Also, I assume node is a pointer. You really haven't provided much information about what you're doing.

Resources