free throws error when trying to free memory - c

Visual Studio 2008 - compiling in C
I am writing a linked list application but when I try and free each node I get an exception thrown. The only thing I can think of is that I allocated my memory in the add function, and maybe globaly I cannot free it in another function. Appart from that I can't think of anything.
Many thanks for any advice,
#include <stdio.h>
#include <stdlib.h>
static struct convert_temp
{
size_t cel;
size_t fah;
struct convert_temp *next;
} *head = NULL, *tail = NULL;
=======
/** Add the new converted temperatures on the list */
void add(size_t cel, size_t fah)
{
struct convert_temp *node_temp = NULL; /* contain temp data */
node_temp = malloc(sizeof(node_temp));
if(node_temp == NULL)
{
fprintf(stderr, "Cannot allocate memory [ %s ] : [ %d ]\n",
__FUNCTION__, __LINE__);
exit(0);
}
/* Assign data */
node_temp->cel = cel;
node_temp->fah = fah;
node_temp->next = NULL;
if(head == NULL)
{
/* The list is at the beginning */
head = node_temp; /* Head is the first node = same node */
tail = node_temp; /* Tail is also the last node = same node */
}
else
{
/* Append to the tail */
tail->next = node_temp;
/* Point the tail at the end */
tail = node_temp;
}
}
=====
/** Free all the memory that was used to allocate the list */
void destroy()
{
/* Create temp node */
struct convert_temp *current_node = head;
/* loop until null is reached */
while(current_node)
{
struct convert_temp *next = current_node->next;
/* free memory */
free(current_node);
current_node = next;
}
/* Set to null pointers */
head = NULL;
tail = NULL;
}

node_temp = malloc(sizeof(node_temp)); is allocating the size of a struct pointer instead of the struct, you should be using sizeof(*node_temp).

This line does not allocate the correct amount of memory:
node_temp = malloc(sizeof(node_temp));
It should instead be this:
node_temp = malloc(sizeof *node_temp);

Change:
node_temp = malloc(sizeof(node_temp));
to:
node_temp = malloc(sizeof(struct convert_temp));
and it will work. sizeof(node_temp) is the size of a pointer (most likely 4 or 8 bytes); you want to allocate the size of the structure

Related

Function to add a node to linked list not working | c

I have the following program which reads words from a text file and creates a single linked list, with each node containing: word, count, next.
When a word already exists in the linked list the count is updated, otherwise, a node is created at the end of the linked list.
All of my functions work, except for the one where I am adding a word to the end of the linked list. There is likely an error with linkage of the nodes?
with my following text file: line1 "my name is natalie", line 2 "my dog is niko"
I should be getting the following output: my(2), name(1), is(2), natalie(1), dog(1), niko(1)
but I am getting: my(2), dog(2), s(1), iko(1), is(1), niko(1)
WHERE IS MY ERROR?
//function to add word to linked list
struct WordNode *addWord(char* word, struct WordNode *wordListHead){
//create new node
struct WordNode *current = malloc(sizeof(struct WordNode));
current->word = word;
current->count = 1;
current->next = NULL;
//
while(1){
if((wordListHead != NULL)&&(wordListHead->next ==NULL)){
//connect
wordListHead->next=current;
break;
}
wordListHead = wordListHead->next;
}
}
called here in main:
char *filename = argv[1];
FILE *fp = fopen(filename, "r");
printf("%s\n", filename);
if (fp == NULL){
printf("Error: unable to open the file ");
printf("%s", filename);
return 1;
}
else {
char *delim = " \t\n,:;'\".?!#$-><(){}[]|\\/*&^%#!~+=_"; // These are our word delimiters.
char line[1000];
char * token;
int count = 0;//count used so that first word of the doc can be created as head node
//create head pointer
struct WordNode *wordListHead = NULL;
//create current pointer
struct WordNode *current = NULL;
//iterate through each line in file
while(fgets(line, 1000, fp)){
//seperate each word
//first word of line
token = strtok(line, delim);
printf("%s\n", token);
if(count == 0){
//first word of document, create first wordnode (head node)
wordListHead = malloc(sizeof(struct WordNode));
wordListHead->word = token;
wordListHead->count = 1;
wordListHead->next = NULL;
}
else{
//check if first word of line exists in linked list
if((doesWordExist(token, wordListHead)) == 0){
//update count
updateCount(token, wordListHead);
}
else{
//create node
addWord(token, wordListHead);
}
}
//iterate through all the other words of line
while ((token=strtok(NULL, delim)) != NULL){
printf("%s\n", token);
//check if name is in linked list
if((doesWordExist(token, wordListHead)) == 0){
//update count
updateCount(token, wordListHead);
}
else{
//create node
addWord(token, wordListHead);
}
}
count++;
}
printWordList(wordListHead);
}
}
struct defined here:
//structure definition of linked list node
#ifndef WORDLISTH
#define WORDLISTH
struct WordNode{
char *word;
unsigned long count;
struct WordNode *next;
};
void printWordList( struct WordNode *wordListHead);
struct WordNode *addWord(char* word , struct WordNode *wordListead);
#endif
other functions for reference:
//function to check if word is in linked list
bool doesWordExist(char* myword, struct WordNode *wordListHead){
while (wordListHead != NULL){
if(strcmp(wordListHead->word, myword) == 0){
return 0;
}
wordListHead= wordListHead-> next;
}
return 1;
}
//function to update the count of word
void updateCount(char* myword, struct WordNode *wordListHead){
while (wordListHead != NULL){
if(strcmp(wordListHead->word, myword) == 0){
//update count value
//capture current count and add 1
int curcount = wordListHead->count;
int newcount = curcount + 1;
wordListHead->count = newcount;
//printf("%d\n", newcount);
}
wordListHead= wordListHead-> next;
}
}
//function to print word list
//takes head node as argument
void printWordList( struct WordNode *wordListHead){
//WordNode *toyptr = wordListHead;
while (wordListHead != NULL){
printf("%s\n", wordListHead->word);
printf("%ld\n", wordListHead->count);
wordListHead = wordListHead -> next;
}
}
When you are storing token into your struct, you are using a pointer that is part of the input buffer.
On a new input line, the tokens gathered from previous lines will be corrupted/trashed.
You need to allocate space to store the token in the struct on the heap. Use strdup for that.
So, in addWord, you want:
current->word = strdup(word);
And in main, you want:
wordListHead->word = strdup(token);
UPDATE:
That's the primary issue. But, your code does a bunch of needless replication.
addWord doesn't handle an empty list. But, if it did there would be no need for main to have separate [replicated] code for the first word and subsequent words on the line.
The strcmp can be incorporated into addWord and it can "do it all". (i.e. a single scan of the list)
For doesWordExist, it returns a bool on a match. If it returned the pointer to the element that matched, updateCount would just have to increment the count [and not rescan the list]. I've updated those functions accordingly, but they are no longer needed due to the changes to addWord
Here's how I would simplify and refactor the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int bool;
#ifdef DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) do { } while (0)
#endif
//structure definition of linked list node
#ifndef WORDLISTH
#define WORDLISTH
struct WordNode {
char *word;
unsigned long count;
struct WordNode *next;
};
void printWordList(struct WordNode *wordListHead);
#endif
//function to add word to linked list
struct WordNode *
addWord(char *word, struct WordNode **list)
{
struct WordNode *curr;
struct WordNode *prev = NULL;
struct WordNode *newnode = NULL;
for (curr = *list; curr != NULL; curr = curr->next) {
if (strcmp(curr->word,word) == 0) {
newnode = curr;
break;
}
prev = curr;
}
// create new node
do {
// word already exists
if (newnode != NULL)
break;
newnode = malloc(sizeof(struct WordNode));
newnode->word = strdup(word);
newnode->count = 0;
newnode->next = NULL;
// attach to tail of list
if (prev != NULL) {
prev->next = newnode;
break;
}
// first node -- set list pointer
*list = newnode;
} while (0);
// increment the count
newnode->count += 1;
return newnode;
}
//function to check if word is in linked list
struct WordNode *
findWord(char *myword, struct WordNode *head)
{
struct WordNode *curr;
for (curr = head; curr != NULL; curr = curr->next) {
if (strcmp(curr->word,myword) == 0)
break;
}
return curr;
}
//function to update the count of word
void
updateCount(char *myword, struct WordNode *head)
{
struct WordNode *match;
match = findWord(myword,head);
if (match != NULL)
match->count += 1;
}
//function to print word list
//takes head node as argument
void
printWordList(struct WordNode *head)
{
struct WordNode *curr;
for (curr = head; curr != NULL; curr = curr->next) {
printf("%s", curr->word);
printf(" %ld\n", curr->count);
}
}
int
main(int argc, char **argv)
{
char *filename = argv[1];
FILE *fp = fopen(filename, "r");
printf("FILE: %s\n", filename);
if (fp == NULL) {
printf("Error: unable to open the file ");
printf("%s", filename);
return 1;
}
// These are our word delimiters.
char *delim = " \t\n,:;'\".?!#$-><(){}[]|\\/*&^%#!~+=_";
char line[1000];
char *token;
// create head pointer
struct WordNode *wordListHead = NULL;
// iterate through each line in file
while (fgets(line, sizeof(line), fp)) {
// seperate each word
// first word of line
char *bp = line;
while (1) {
token = strtok(bp, delim);
bp = NULL;
if (token == NULL)
break;
dbgprt("TOKEN1: %s\n", token);
addWord(token,&wordListHead);
}
}
printWordList(wordListHead);
return 0;
}
UPDATE #2:
Note that addWord and findWord replicate code. The first part of addWord is [essentially] duplicating what findWord does.
But, addWord can not just use findWord [which would be desirable] because findWord, if it fails to find a match returns NULL. In that case, it doesn't [have a way to] communicate back the last element (i.e. the "tail" of the list) which addWord needs to append to.
While we could add an extra argument to findWord to propagate this value back, a better solution is to create a different struct that defines a "list".
In the existing code, we are using a "double star" pointer to the head word node as a "list". Using a separate struct is cleaner and has some additional advantages.
We can just pass around a simple pointer to the list. We no longer need to worry about whether we should be passing a double star pointer or not.
Although we're only using a singly linked list, a separate list struct helps should we wish to convert the list to a doubly linked list [later on].
We just pass around a pointer to the list, and the list can keep track of the head of the list, the tail of the list, and the count of the number of elements in the list.
Linked lists lend themselves well to sorting with mergesort. The list count helps make that more efficient because it is much easier to find the "midpoint" of the list [which a mergesort would need to know].
To show the beginnings of the doubly linked list, I've added a prev element to the word struct. This isn't currently used, but it hints at the doubly linked version.
I've reworked all functions to take a pointer to a list, rather than a pointer to the head node.
Because the list struct has a tail pointer, addWord can now call findWord. If findWord does not find a match, addWord can simply use the head/tail pointers in the list to find the correct insertion point.
To simplify a bit more, I've changed the word node [and the list struct] to use some typedef statements.
Also, it's more usual/idiomatic to have the dominant struct pointer be the first argument, so I've reversed the order of the arguments on some of the functions.
Anyway, here's the [further] refactored code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int bool;
#ifdef DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) do { } while (0)
#endif
//structure definition of linked list node
#ifndef WORDLISTH
#define WORDLISTH
// word frequency control
typedef struct WordNode Word_t;
struct WordNode {
const char *word;
unsigned long count;
Word_t *next;
Word_t *prev;
};
// word list control
typedef struct {
Word_t *head;
Word_t *tail;
unsigned long count;
} List_t;
void printWordList(List_t *list);
#endif
// create a list
List_t *
newList(void)
{
List_t *list;
list = calloc(1,sizeof(*list));
return list;
}
// function to check if word is in linked list
Word_t *
findWord(List_t *list,const char *myword)
{
Word_t *curr;
for (curr = list->head; curr != NULL; curr = curr->next) {
if (strcmp(curr->word,myword) == 0)
break;
}
return curr;
}
//function to add word to linked list
Word_t *
addWord(List_t *list,const char *word)
{
Word_t *match;
do {
// try to find existing word
match = findWord(list,word);
// word already exists
if (match != NULL)
break;
// create new node
match = malloc(sizeof(*match));
match->word = strdup(word);
match->count = 0;
match->next = NULL;
// attach to head of list
if (list->head == NULL)
list->head = match;
// append to tail of list
else
list->tail->next = match;
// set new tail of list
list->tail = match;
// advance list count
list->count += 1;
} while (0);
// increment the word frequency count
match->count += 1;
return match;
}
//function to update the count of word
void
updateCount(List_t *list,const char *myword)
{
Word_t *match;
match = findWord(list,myword);
if (match != NULL)
match->count += 1;
}
//function to print word list
//takes head node as argument
void
printWordList(List_t *list)
{
Word_t *curr;
for (curr = list->head; curr != NULL; curr = curr->next) {
printf("%s", curr->word);
printf(" %ld\n", curr->count);
}
}
int
main(int argc, char **argv)
{
char *filename = argv[1];
FILE *fp = fopen(filename, "r");
printf("FILE: %s\n", filename);
if (fp == NULL) {
printf("Error: unable to open the file ");
printf("%s", filename);
return 1;
}
// These are our word delimiters.
char *delim = " \t\n,:;'\".?!#$-><(){}[]|\\/*&^%#!~+=_";
char line[1000];
char *token;
// create list/head pointer
List_t *list = newList();
// iterate through each line in file
while (fgets(line, sizeof(line), fp) != NULL) {
// seperate each word
// first word of line
char *bp = line;
while (1) {
token = strtok(bp, delim);
bp = NULL;
if (token == NULL)
break;
dbgprt("TOKEN1: %s\n", token);
addWord(list,token);
}
}
printWordList(list);
return 0;
}
#Craig Estey has provided a great answer for you, so don't change your answer selection, but rather than just leave you a link in the comments, there are a couple of important ways of looking at list operations that may help, and you must use a memory/error checking program to validate your use of allocated memory, especially when dealing with list operations.
Take a node holding a string with a reference count of the additional number of times the string occurs, as in your case, e.g.
typedef struct node_t { /* list node */
char *s;
size_t refcnt;
struct node_t *next;
} node_t;
Iterating With Address of Node & Pointer to Node Eliminates Special Cases
Using both the address of the node and pointer to node is discussed in Linus on Understanding Pointers.
For example, where you need to check if (list->head == NULL) to add the first node to the list, if iterating with both the address of the node and pointer to node, you simply assign the allocated pointer to your new node to the address of the current node. This works regardless whether it is the first, middle or last node. It also eliminates having to worry about what the previous node was when removing nodes from the list. At the node to delete, you simply assign the contents of the next node to the current address and free the node that was originally there. This reduces your add node function to something similar to:
/** add node in sort order to list.
* returns pointer to new node on success, NULL otherwise.
*/
node_t *add_node (node_t **head, const char *s)
{
node_t **ppn = head, /* address of current node */
*pn = *head; /* pointer to current node */
while (pn) { /* iterate to last node */
if (strcmp (pn->s, s) == 0) { /* compare node string with string */
pn->refcnt += 1; /* increment ref count */
return *ppn;
}
ppn = &pn->next; /* ppn to address of next */
pn = pn->next; /* advance pointer to next */
}
return *ppn = create_node (s); /* allocate and return node */
}
(note: by delaying allocation for the new node and string (create_node (s) above), you avoid allocating until you know the string needs to be added -- simplifying memory handling)
As mentioned in the comments above, this combines your doesWordExist() traversal of the list and your addWord() traversal to find the end into a single traversal. If there are hundreds of thousands of nodes in your list, you don't want to traverse the list multiple times.
Using strdup() is Fine, but know it's POSIX not standard C
strdup() is handy for duplicating strings and assigning the result to a new pointer, but strdup() is provided by POSIX, so not all implementation will provide it. Additionally, strdup() allocates memory, so just as with any function that allocates memory, you must check that the result is not NULL before using the pointer that is returned. You can avoid the potential portability issue by writing a short equivalent. For example in the create_node() shown above, it does:
/** helper function to allocate node, and storage for string.
* copies string to node and initializes node->next pointer NULL
* and node->refcnt zero. returns pointer to allocated node on success,
* NULL otherwise.
*/
node_t *create_node (const char *s)
{
size_t len = strlen (s); /* get string length */
node_t *node = malloc (sizeof *node); /* allocate node */
if (!node) { /* validate EVERY allocation */
perror ("create_node: malloc node");
return NULL;
}
if (!(node->s = malloc (len + 1))) { /* allocate for string */
perror ("create_node: malloc node->s");
free (node); /* on failure, free node before returning NULL */
return NULL;
}
memcpy (node->s, s, len+1); /* copy string to node */
node->refcnt = 0; /* initialize ref count */
node->next = NULL; /* initialze next NULL */
return node; /* return allocated & initialized node */
}
Freeing Allocated Memory
Any time you write code creating data structures, they need to be able to clean up after themselves in the event you want to remove a single node, or are done using the list. This becomes imperative when you create lists, etc. that are declared and used solely within functions below main() as the memory isn't freed on the function return. With main(), on return the program exits and will free all allocated memory. However if the list is created and used solely below main() a memory leak will result each time that function is called if the list memory is not freed before return. A function that frees all memory is short and easy to write, e.g.
/** delete all nodes in list */
void del_list (node_t *head)
{
node_t *pn = head; /* pointer to iterate */
while (pn) { /* iterate over each node */
node_t *victim = pn; /* set victim to current */
pn = pn->next; /* advance pointer to next */
free (victim->s); /* free current string */
free (victim); /* free current node */
}
}
(**no need to worry about the refcnt since you are deleting the list)
A short example including all of these points, as well as a function del_node() to remove a single node from the list (or reduce the refcnt without removing the node if the refcnt is non-zero) can be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
typedef struct node_t { /* list node */
char *s;
size_t refcnt;
struct node_t *next;
} node_t;
/** helper function to allocate node, and storage for string.
* copies string to node and initializes node->next pointer NULL
* and node->refcnt zero. returns pointer to allocated node on success,
* NULL otherwise.
*/
node_t *create_node (const char *s)
{
size_t len = strlen (s); /* get string length */
node_t *node = malloc (sizeof *node); /* allocate node */
if (!node) { /* validate EVERY allocation */
perror ("create_node: malloc node");
return NULL;
}
if (!(node->s = malloc (len + 1))) { /* allocate for string */
perror ("create_node: malloc node->s");
free (node); /* on failure, free node before returning NULL */
return NULL;
}
memcpy (node->s, s, len+1); /* copy string to node */
node->refcnt = 0; /* initialize ref count */
node->next = NULL; /* initialze next NULL */
return node; /* return allocated & initialized node */
}
/** add node in sort order to list.
* returns pointer to new node on success, NULL otherwise.
*/
node_t *add_node (node_t **head, const char *s)
{
node_t **ppn = head, /* address of current node */
*pn = *head; /* pointer to current node */
while (pn) { /* iterate to last node */
if (strcmp (pn->s, s) == 0) { /* compare node string with string */
pn->refcnt += 1; /* increment ref count */
return *ppn;
}
ppn = &pn->next; /* ppn to address of next */
pn = pn->next; /* advance pointer to next */
}
return *ppn = create_node (s); /* allocate and return node */
}
/** print all nodes in list */
void prn_list (node_t *head)
{
if (!head) { /* check if list is empty */
puts ("list-empty");
return;
}
for (node_t *pn = head; pn; pn = pn->next) /* iterate over each node */
printf ("%-24s %4zu\n", pn->s, pn->refcnt); /* print string an refcount */
}
/** delete node with string s from list (for loop) */
void del_node (node_t **head, const char *s)
{
node_t **ppn = head; /* address of node */
node_t *pn = *head; /* pointer to node */
for (; pn; ppn = &pn->next, pn = pn->next) {
if (strcmp (pn->s, s) == 0) { /* does string match */
if (pn->refcnt) { /* ref count > 0 */
pn->refcnt -= 1; /* decrement ref count */
return; /* done */
}
*ppn = pn->next; /* set content at address to next */
free (pn); /* free original pointer */
break;
}
}
}
/** delete all nodes in list */
void del_list (node_t *head)
{
node_t *pn = head; /* pointer to iterate */
while (pn) { /* iterate over each node */
node_t *victim = pn; /* set victim to current */
pn = pn->next; /* advance pointer to next */
free (victim->s); /* free current string */
free (victim); /* free current node */
}
}
int main (int argc, char **argv) {
char buf[MAXC]; /* read buffer */
const char *delim = " \t\n.,;?!()"; /* strtok delimiters */
node_t *list = NULL; /* pointer to list (must initialize NULL */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) /* read all lines in file */
/* tokenize line based on delim */
for (char *p = strtok (buf, delim); p; p = strtok (NULL, delim)) {
if (ispunct(*p)) /* if word is punctionation, skip */
continue;
add_node (&list, p); /* add node or increment refcnt */
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
puts ("string refcnt\n" /* heading */
"-------------------------------");
prn_list (list); /* print contents of list */
del_list (list); /* free all list memory */
return 0;
}
Take a look at the characters included in delim to use with strtok() as well as the use of ispunct() to skip tokens that end up beginning with punctuation (which allows hyphenated words, but skips hyphens used alone as sentence continuations, etc....)
Example Input File
$ cat dat/tr_dec_3_1907.txt
No man is above the law and no man is below it;
nor do we ask any man's permission when we require him to obey it.
Obedience to the law is demanded as a right; not asked as a favor.
(Theodore Roosevelt - December 3, 1907)
Example Use/Output
$ ./bin/lls_string_nosort_refcnt dat/tr_dec_3_1907.txt
string refcnt
-------------------------------
No 0
man 1
is 2
above 0
the 1
law 1
and 0
no 0
below 0
it 1
nor 0
do 0
we 1
ask 0
any 0
man's 0
permission 0
when 0
require 0
him 0
to 1
obey 0
Obedience 0
demanded 0
as 1
a 1
right 0
not 0
asked 0
favor 0
Theodore 0
Roosevelt 0
December 0
3 0
1907 0
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to ensure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/lls_string_nosort_refcnt dat/tr_dec_3_1907.txt
==8528== Memcheck, a memory error detector
==8528== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==8528== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==8528== Command: ./bin/lls_string_nosort_refcnt dat/tr_dec_3_1907.txt
==8528==
string refcnt
-------------------------------
No 0
man 1
is 2
above 0
the 1
law 1
and 0
no 0
below 0
it 1
nor 0
do 0
we 1
ask 0
any 0
man's 0
permission 0
when 0
require 0
him 0
to 1
obey 0
Obedience 0
demanded 0
as 1
a 1
right 0
not 0
asked 0
favor 0
Theodore 0
Roosevelt 0
December 0
3 0
1907 0
==8528==
==8528== HEAP SUMMARY:
==8528== in use at exit: 0 bytes in 0 blocks
==8528== total heap usage: 73 allocs, 73 frees, 6,693 bytes allocated
==8528==
==8528== All heap blocks were freed -- no leaks are possible
==8528==
==8528== For counts of detected and suppressed errors, rerun with: -v
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
You already have a solution to your immediate problem, but going forward in your project consider some of the tips above to eliminate multiple traversals of your list, and the portability (and validation) issues surrounding strdup(). Good luck with your coding.

Needing advice for implementing malloc and free in C

For school, I need to write a program that uses my own implementation of malloc and free. I need to be able to report on all the chunks of memory in my 'heap', whether it's allocated or not. I feel like I've written good code to do so, but evidently not. The first few times I ran it, the report kept reporting on the same address forever. While trying to debug that, there came a point that the program wouldn't even let me start allocate space to use as my 'heap', it would just get a segmentation fault and quit. Any pointers on where I'm going wrong, or even to clean up my code at all, would be super helpful.
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#define WORDSIZE 8
#define ALLOCMAGIC 0xbaddecaf
#define FREEMAGIC 0xdeadbeef
typedef struct __header_t {
size_t size;
int magic;
} header_t;
typedef struct __node_t {
size_t size;
struct __node_t *next;
} node_t;
node_t *head = NULL;
// Find the free node that occurs just before the given node.
node_t *findLastFree(node_t * node) {
// Initialize some pointers to traverse the free node linked list;
node_t *lastFree = head;
node_t *nextFree = lastFree->next;
// Traverse linked list until the last node's pointer is pointed to NULL,
// meaning the end of the list.
while (nextFree != NULL) {
// Check if target node is less than the next node, meaning the target node
// is between last and next. If so, then return last node.
if (node < nextFree) {
return lastFree;
}
lastFree = nextFree;
nextFree = lastFree->next;
}
// If we have reached the end of the list and the target node is still greater
// than the last node, return last node.
return lastFree;
}
// If the given pointer is allocated, deallocate the space and coalesce the free
// node list.
void myFree(void *ptr) {
// Initialize some free node pointers and assert that the given pointer is
// the beginning of allocated space.
node_t *lastFree;
node_t *nextFree;
node_t *newFree;
header_t *block = ((header_t *) ptr) - 1;
assert(block->magic == ALLOCMAGIC);
// Set this block's signal to free space
block->magic = FREEMAGIC;
// Typecast the block into a free node and set it's size.
size_t size = block->size + sizeof(header_t);
newFree = (node_t *) block;
newFree->size = size;
// Check if node is before the first free node. If so set the new node as
// the new head. If not, then handle node as it occurs after head.
if (newFree < head) {
nextFree = head;
// Check if new node ends at the start of head. If so, merge them
// into a single free node. Else point the new node at the previous head.
// Either way, set new free as the new head.
if ((newFree + newFree->size) == head) {
newFree->next = head->next;
newFree->size = newFree->size + head->size;
} else {
newFree->next = head;
}
head = newFree;
} else {
// Set the free nodes for before and after the new free node.
lastFree = findLastFree(newFree);
nextFree = lastFree->next;
// Check if new node is the last node. If so, point the previous final
// node at the new node and point the new node at NULL.
if (nextFree == NULL) {
lastFree->next = newFree;
newFree->next = NULL;
}
// Check if end of new node is touching next node. If so, merge them
// into a single free node. Else point new free and next free.
if ((newFree + newFree->size) == nextFree) {
newFree->next = nextFree->next;
newFree->size = newFree->size + nextFree->size;
} else {
newFree->next = nextFree;
}
// Check if start of new node is touching last free node. If so, merge
// them into a single free node. Else point last's next to new free.
if ((lastFree + lastFree->size) == newFree) {
lastFree->next = newFree->next;
lastFree->size = lastFree->size + newFree->size;
} else {
lastFree->next = newFree;
}
}
}
// Split the given free node to fit the given size. Create a new node at the
// remainder and rearrange the free list to accomodate.
void splitBlock(node_t *node, size_t size) {
// Create a new pointer at the end of the requested space.
void *newBlock = node + size;
// Set the bits of the new space as if it were allocated then freed.
header_t *hptr = (header_t *) newBlock;
hptr->size = (node->size - size - sizeof(header_t));
hptr->magic = FREEMAGIC;
// Typecast the new space into a node pointer. Reinsert it into the free
// node list.
node_t *newFree = (node_t *) newBlock;
newFree->size = node->size - size;
newFree->next = node->next;
node_t *lastFree = findLastFree(newFree);
lastFree->next = newFree;
}
// Find a free node that can fit the given size. Split the node so no space is
// wasted. If no node can fit requested size, increase the heap size to accomodate.
void *findFirstFit(size_t size) {
// Create a node pointer to traverse the free node list.
node_t *node = head;
// Traverse the list until the end is reached.
while(node != NULL) {
// Check if the node can accomodate the requested size.
if (node->size >= size) {
// Split the current node at the requested size and return a pointer
// to the start of the requested space.
splitBlock(node, size);
return (void *) node;
}
node = node->next;
}
// No free space could fit requested size, so request more space at the end
// of the heap.
void *newspace = sbrk(size);
assert(newspace >= 0);
return newspace;
}
// Allocate a block of space for the given size and return a pointer to the start
// of the freed space.
void *myMalloc(size_t need) {
// Round the given size up to the next word size. Add the size of a header to
// the amount actually needed to allocate.
need = (need + WORDSIZE - 1) & ~(WORDSIZE - 1);
size_t actual = need + sizeof(header_t);
// Find a free node that can accomodate the given size. Check it is valid.
void *firstfit = findFirstFit(actual);
assert(firstfit >= 0);
// Create a header for the newly allocated space.
header_t *hptr = (header_t *) firstfit;
hptr->magic = ALLOCMAGIC;
hptr->size = need;
return (void *) (hptr + 1);
}
// Print a report on the space starting at the given pointer. Return a pointer to
// the start of the next block of space.
void *reportAndGetNext(void *ptr) {
void *nextptr;
header_t *hptr = (header_t *) ptr;
// Check if the pointer is pointing to allocated space.
if (hptr->magic == ALLOCMAGIC) {
// Report the characteristics of the current block.
printf("%p is ALLOCATED starting at %p and is %zd bytes long.\n", hptr, (hptr + 1), hptr->size);
// Set the next pointer to be returned.
nextptr = hptr + hptr->size + sizeof(header_t);
} else {
// Cast the pointer as a free node. Set the next pointer to be returned.
node_t *free = (node_t *) ptr;
nextptr = free + free->size;
// Report the characteristics of the current block.
printf("%p is FREE for %zd bytes.\n", hptr, free->size);
}
return nextptr;
}
// Report on all blocks of space contained within the heap space, starting at the
// given pointer.
void report(void* startheap) {
void *ptr = startheap;
void *end = sbrk(0);
int count = 50;
printf("Current Status of Heap:\n");
while (ptr != NULL && count > 0) {
ptr = reportAndGetNext(ptr);
count = count - 1;
}
printf("Heap Length: %zd \n", (end - startheap));
}
int main(void) {
void *start = sbrk(4096);
assert(start >= 0);
head = (node_t *) start;
head->size = 4096;
head->next = NULL;
printf("Allocating block 1");
void *ptr1 = myMalloc(26);
void *ptr2 = myMalloc(126);
report(start);
myFree(ptr1);
myFree(ptr2);
return 0;
}
The first obvious error I see is with pointer arithmentic. SplitBlock is trying to split size bytes from the front of a block, but when you do:
void splitBlock(node_t *node, size_t size) {
// Create a new pointer at the end of the requested space.
void *newBlock = node + size;
Your newBlock pointer is actually size * sizof(node_t) bytes into the block -- which may well be past the end of the block. You need to cast node to a char * before doing pointer arithmetic with it if you want byte offsets. However, you may then run into alignment issues...

Runtime error while using stack or atoi()

#define MAXL 256
First pass: in = "25 7 * 14 - 6 +"; run smoothly with correct answer.
Second pass: in = "1 24 3 + * 41 -"; program stopped right after outputting Num got in: 41 Expected: continue loop and get in the minus sign then pop(s) and subtract 41
I'm guessing that my program ran out of allocated space because of the free() didn't do their job as I expected but I'm not sure.
Any help would be greatly appreciated. Thank you!
double evaluatePost(char * in)
{
double * op1 = NULL, * op2 = NULL, * msgr = NULL;
int i, j;
char * c = {0}, tempExp[MAXL] = {0};
char ** token = NULL;
Stack * s = createStack();
strcpy(tempExp, in); /* Copy in to a temporary array so strtok will not destroy in */
for(c = strtok(tempExp, " "); c != NULL; ++i, c = strtok(NULL, " "))
{
if(isdigit(c[0]))
{
printf("\nNum got in: %s\n", c); /* Crash right after this line output 41 */
system("PAUSE");
msgr = (double*)malloc(sizeof(double)); /* I made a malloc check here, it never showed error */
*msgr = atoi(c); /* I don't know if it crash at this line or the next one */
push(s, msgr); /* stack has no limit, receives stack* and void* */
/* It never got pass to here after output 41 */
}
else
{
op2 = (double *)pop(s);
op1 = (double *)pop(s);
printf("\n%f %f %s\n", *op1, *op2, c);
system("PAUSE");
msgr = (double*)malloc(sizeof(double));
if(!msgr)
{
printf("Memory allocation failed.\n");
system("PAUSE");
exit(1);
}
switch(*c)
{
case '+': *msgr = (*op1 + *op2); break;
case '-': *msgr = (*op1 - *op2); break;
case '*': *msgr = (*op1 * *op2); break;
case '/': *msgr = (*op1 / *op2); break;
}
printf("\n%.1f\n", *msgr);
system("PAUSE");
/* Free the memory before they become orphans */
free(op1), free(op2);
push(s, msgr);
}
}
returnVal = *((double *)pop(s));
makeEmpty(s);
return returnVal;
}
void push(Stack * stack, void * dataInPtr)
{
/* Define a new StackNode */
StackNode * newPtr;
/* Get some Memory */
newPtr = (StackNode*)malloc(sizeof(StackNode));
if(!newPtr)
{
printf("Out of memory");
system("PAUSE");
exit(1);
}
/* Assign dataIn to dataPtr */
newPtr->dataPtr = dataInPtr;
/* Make the links */
newPtr->link = stack->top; /* Point both to top */
stack->top = newPtr; /* newPtr at top pointed to be head */
(stack->count)++;
}
void * pop(Stack * stack)
{
/* Hold the data */
void * dataOutPtr;
StackNode * temp;
/* Check if stack is empty */
if(stack->count == 0)
dataOutPtr = NULL;
else
{
/* Get the data and remove the node */
temp = stack->top; /* temp points to top */
dataOutPtr = stack->top->dataPtr; /* dataOutPtr has data */
stack->top = stack->top->link; /* stack moves to next node */
temp->link = NULL; /* break top node off stack */
free(temp); /* frees memory */
(stack->count)--;
}
return dataOutPtr;
}
typedef struct node
{
void * dataPtr;
struct Node * link;
} StackNode;
typedef struct
{
int count;
StackNode * top;
} Stack;
Your problem may lie here:
You are freeing the Stack node in pop()
temp = stack->top; /* temp points to top */
dataOutPtr = stack->top->dataPtr; /* dataOutPtr has data */
stack->top = stack->top->link; /* stack moves to next node */
temp->link = NULL; /* break top node off stack */
free(temp); /* frees memory */
And after that you are freeing the data pointer in the node in evaluatePost():
free(op1), free(op2);
The sequence freeing the memory should always be in reverse order of malloc i.e. you should allocate Node first and then node data and for freeing free the node data first, and then Node itself.
You are facing problem with some input and not with some other input, because this is undefined behavior.
To know more about undefined behavior in C, you can search for related questions in SO.
You can easily add the ability to traverse over all the nodes in your stack without freeing them. This comes in handy, if say, after pushing all nodes you need to use the collection and don't want to pop and free the data, or if you need to update the nodes in some way before popping them. All you need to do is add a single tail pointer to your stack which will hold the address of the first node pushed onto the stack. e.g.:
typedef struct
{
int count;
StackNode *top;
StackNode *tail;
} Stack;
Why? Since you have a StackNode->link, your data is effectively in linked-list form anyway. Adding a tail pointer that points to the first node pushed onto the stack, simply gives an easy way to know when to stop iterating over your nodes. With a few minor tweaks, you can then do what you attempted - iterate over all the nodes in your stack without having to pop/free the nodes as you do it.
Here is a short examples showing the minor tweaks needed. Also notice the cleanup removes all casts of malloc (don't do it) and a couple of cleanups on the malloc calls themselves:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
void *dataPtr;
struct node *link;
} StackNode;
typedef struct
{
int count;
StackNode *top;
StackNode *tail;
} Stack;
Stack *stackcreate ()
{
Stack *s = malloc (sizeof *s);
if (!s) {
fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
exit (EXIT_FAILURE);
}
s->count = 0;
s->top = s->tail = NULL;
return s;
}
void push(Stack * stack, void * dataInPtr)
{
if (!stack) return;
/* Define a new StackNode & allocate */
StackNode *newPtr = malloc (sizeof *newPtr);
if(!newPtr)
{
fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
exit (EXIT_FAILURE);
}
/* Assign dataIn to dataPtr */
newPtr->dataPtr = dataInPtr;
newPtr->link = stack->top; /* Point both to top */
/* Make the links */
if (!stack->top)
stack->tail = newPtr;
stack->top = newPtr; /* newPtr at top pointed to be head */
(stack->count)++;
}
void * pop(Stack * stack)
{
/* Hold the data */
void * dataOutPtr;
StackNode * temp;
/* Check if stack is empty */
if(stack->count == 0)
dataOutPtr = NULL;
else
{
/* Get the data and remove the node */
temp = stack->top; /* temp points to top */
dataOutPtr = stack->top->dataPtr; /* dataOutPtr has data */
stack->top = stack->top->link; /* stack moves to next node */
temp->link = NULL; /* break top node off stack */
free(temp); /* frees memory */
(stack->count)--;
if (!stack->top) stack->tail = NULL;
}
return dataOutPtr;
}
int main (void) {
char *lines[] = { "my cat has more...",
"has lots of fleas, ",
"my dog, the lab, " };
size_t i = 0;
size_t entries = sizeof lines/sizeof *lines;
Stack *stack = stackcreate ();
for (i = 0; i < entries; i++)
push (stack, (void *)lines[i]);
printf (" \niterating over nodes in stack without popping\n\n");
StackNode *p;
for (p = stack->top; ;p = p->link) {
printf (" %s\n", (char *)p->dataPtr);
if (p == stack->tail)
break;
}
printf ("\n popping items from stack\n\n");
while (stack->top) {
printf (" %s\n", (char *)pop (stack));
}
printf ("\n");
return 0;
}
Example/Output
$ ./bin/stack_iter
iterating over nodes in stack without popping
my dog, the lab,
has lots of fleas,
my cat has more...
popping items from stack
my dog, the lab,
has lots of fleas,
my cat has more...

Create Fixed Size Linked List in C

I have created a linked list in C that is used to store data which is then modified as required. In creating the linked list I have used the following
struct car_elements
{
char car_rego[7];
double time_parked;
struct car_elements *next;
};
typedef struct car_elements car;
/* Defined as global variable to hold linked list */
car *head = NULL;
car *SetupCars()
{
car *ptr = head;
car *new_car = NULL;
new_car = (car*) malloc(sizeof(car));
if (!new_car)
{
printf("\nUnable to allocate memory!\n");
exit(1);
}
strcpy(new_car->car_rego, "empty");
new_car->time_parked = time(NULL);
new_car->next = NULL;
if (ptr == NULL)
{
return (new_car);
}
else
{
while (ptr->next)
{
ptr = ptr->next;
}
ptr->next = new_car;
return (head);
}
}
From main I call the following to create the linked list
for(int i = 0; i<TOTAL_CARS; i++) {
head = SetupCars(head);
}
The problem is that now I have a memory leak - Is there a better way to create a fixed size linked list. At the end of the program running I can
free(head);
However I cannot call within SetupCars method
free(new_car);
I could create new_car as a global variable I guess and free it at the end of the program but I cannot help but feel there is a better way to do it. I don't think global variables are evil if used properly however I would appreciate some advice.
WHy not just free it at the end? SOmething like this:
car *tofree;
car *ptr = head;
while(ptr) {
tofree = ptr;
ptr = ptr->next;
free(tofree);
}
You need a function to free the entire list, like:
void free_cars(car*p) {
while (p != NULL) {
car* nextp = p->next;
free (p);
p = nextp;
}
}
So you would call
free_cars (head);
head = NULL;
Perhaps even by having a macro
#define DELETE_CARS(CarsVar) do { \
free_cars(CarsVar); CarsVar = NULL; } while(0)
then just write DELETE_CARS(head); later in your code.
And indeed, manual memory management is painful, you need to avoid memory leaks. Tools like valgrind can be helpful. And you could consider instead to use Boehm's garbage collector, so use GC_MALLOC instead of malloc and don't bother freeing memory.... Read more about garbage collection.
Keep car *head as a global var. For SetupCars:
void SetupCars() /* void will do, unless you want a copy of the new "car" */
{
car *new_car = NULL;
new_car = malloc(sizeof *new_car); /* don't need to cast return value of malloc */
/* do checks and setup new_car... */
if (head == NULL) /* first element */
{
head = new_car;
}
else /* easier to add new_car as the FIRST element instead of last */
{
new_car->next = head;
head = new_car;
}
}
From main you create the linked list the same way:
for(int i = 0; i<TOTAL_CARS; i++) {
SetupCars(); /* without any arguments */
}
Then at the end, you loop through the list and free the objects. As Manoj Pandey posted in his answer:
car *tofree;
car *ptr = head;
while(ptr) {
tofree = ptr;
ptr = ptr->next;
free(tofree);
}

LinkedList - How to free the memory allocated using malloc

I have a very simple C code for constructing a Singly Linked list as below, in which I allocate memory for each node dynamically using malloc. At the end of code, I want to free the memory for each node allocated, was wondering how to go about it - If I start from head node first and free it, the pointers to the subsequent nodes are lost and memory leak happens.
Other way is start from head node and keep storing the node pointer in a separate array of pointers or something, traverse the list till the tail pointer while storing the node pointers, and once reach the tail node, store that also to the other array of pointers and start freeing from that array index backwards until the head node is free'ed.
Is that the only way to achieve what I am trying to do?
In case if I dont want to use second buffer, how do I go about it.
#include "stdio.h"
#include "stdlib.h"
struct lnk_lst
{
int val;
struct lnk_lst * next;
};
typedef struct lnk_lst item;
main()
{
item * curr, * head;
int i,desired_value;
head = NULL;
for(i=1;i<=10;i++)
{
curr = (item *)malloc(sizeof(item));
curr->val = i;
curr->next = head;
head = curr;
}
curr = head;
while(curr) {
printf("%d\n", curr->val);
curr = curr->next;
}
//How to free the memory for the nodes in this list?
for(i=1;i<=10;i++)
{
free()//?? What logic here
}
}
The usual way is with (pseudo-code first):
node = head # start at the head.
while node != null: # traverse entire list.
temp = node # save node pointer.
node = node.next # advance to next.
free temp # free the saved one.
head = null # finally, mark as empty list.
The basic idea is to remember the node to free in a separate variable then advance to the next before freeing it.
You only need to remember one node at a time, not the entire list as you propose.
In terms of what you need to add to your code, you can, during deletion, use head as the continuously updating list head (as it's meant to be) and curr to store the item you're currently deleting:
while ((curr = head) != NULL) { // set curr to head, stop if list empty.
head = head->next; // advance head to next element.
free (curr); // delete saved pointer.
}
This is a little shorter than the pseudo-code above simply because it takes advantage of C "shorthand" for some operations.
I use something like this:
for (p = curr; NULL != p; p = next) {
next = p->next;
free(p);
}
Your free code should be as follows:
lnk_lst temp = null;
while(head)
{
temp = head->next;
free(head);
head = temp;
}
Also I would like to add after your malloc you probably want to check whether the mem was allocated successfully.. something like
if(curr)
You traverse the list using the same logic as above. You save the curr->next pointer somewhere, free the curr struct and assign curr with the saved curr->next pointer
Content of Garbage Collector.h
#include <stdlib.h>
#include <stdint.h>
#define Stack struct _stack
#define _MALLOC_S(type,num) (type *)_GC_malloc(sizeof(type)*num)
#pragma pack(1)
//Structure for adressing alocated memory into.
Stack {
int *adress_i;
char *adress_c;
float *adress_f;
double *adress_d;
Stack *next;
};
//Safe malloc
void *_GC_malloc(size_t size)
{
void* ptr = malloc(size);
if(ptr == NULL)
return _GC_malloc(size);
else
return ptr;
}
//Push new element on Stack after every malloc
void Add_New(int *i, float *f , double *d , char *c , Stack *p)
{
Stack *q = _MALLOC_S(Stack,1);
q->adress_i = i;
q->adress_f = f;
q->adress_c = c;
q->adress_d = d;
q->next = p->next;
p->next = q;
q = NULL;
}
//before ending program remove adresses that was allocated in memory, and pop entire Stack
void Free_All(Stack *p)
{
//free head (dummy element)
Stack *Temp = p->next;
Stack *_free = p;
free(_free);
void *oslobodi;
while(Temp != NULL)
{
_free = Temp;
Temp = _free->next;
if(_free->adress_i != NULL){
oslobodi = _free->adress_i;
free((int *)oslobodi);
}
else if(_free->adress_c != NULL){
oslobodi = _free->adress_c;
free((char *)oslobodi);
}
else if(_free->adress_f != NULL){
oslobodi = _free->adress_f;
free((float *)oslobodi);
}
else{
oslobodi = _free->adress_d;
free((double *)oslobodi);
}
free(_free);
}
_free = p = Temp;
}
/*
declare variable (var) and dinamicly alocate memory with simple macro,
and add to stack of linked list
*/
#define obj_int(var) int *var = _MALLOC_S(int,1); *var = 0; Add_New(var, NULL, NULL, NULL, Head);
#define obj_char(var) char *var = _MALLOC_S(char,1); *var = 0; Add_New(NULL, NULL, NULL, var, Head);
#define obj_float(var) float *var = _MALLOC_S(float,1); *var = 0; Add_New(NULL, var, NULL, NULL, Head);
#define obj_double(var) double *var = _MALLOC_S(double,1); *var = 0; Add_New(NULL, NULL, var, NULL, Head);
#define obj_struct(_type,_name) struct _type _*name = (struct _type *)malloc(sizeof(struct _type));
#define _INIT_ROW(var,num) for(int i = 0; i < num; i++) var[i] = 0;
/*
same, but for row!
*/
#define row_int(var, num) int *var = _MALLOC_S(int,num); _INIT_ROW(var,num) Add_New(var, NULL, NULL, NULL, Head);
#define row_char(var, num) char *var = _MALLOC_S(char,num); _INIT_ROW(var,num) Add_New(NULL, NULL, NULL, var, Head);
#define row_float(var, num) float *var = _MALLOC_S(float,num); _INIT_ROW(var,num) Add_New(NULL, var, NULL, NULL, Head);
#define row_double(var, num) double *var = _MALLOC_S(double,num); _INIT_ROW(var,num) Add_New(NULL, NULL, var, NULL, Head);
#define string(var, value) row_char(var, (strlen(value)+1)) strcpy(var, value);
/* with this you create a Stack and allocate dummy element */
#define Main(_type) _type main(void) { Stack *Head = _MALLOC_S(Stack,1); Head->next = NULL; Stack *_q_struct;
/* with this macro you call function for dealocate memory (garbage collecting)*/
#define End Free_All(Head); }
/*same thing for the other functions*/
#define Function(name_function, _type, ...) _type name_function(##__VA_ARGS__) { Stack *Head = _MALLOC_S(Stack,1); Head->next = NULL;
#define End_Ret(ret_var) Free_All(Head); return (ret_var); }
#define Call(name_function, ...) name_function(##__VA_ARGS__)
#define Define_Function(name_function, _type, ...) _type name_function(##__VA_ARGS__);
Example of some_program.c
P.S. header systemIO is group of more headers like this above! :)
Main(void)
int num_elements = 10;
row_int(row_elements, num_elements); //alocating row_elements object
for(int i = 0; i < num_elements; i++)
row_elements[i] = i; //initializing row_elements
End //Garbage delete row_elements and end of program
// row_int[0] = 0, row_int[1] = 1 ....

Resources