Implementing and using a dynamic array in C - c

I'm trying to make a list of students that stores structs using a dynamically allocated array. For this I have the following structs:
typedef struct s_student
{
char name[64];
int matrikelNummer;
} student;
typedef struct s_studentList
{
student* students;
int numberOfStudents;
} studentList;
This is how I use them so far:
int main(int argc, char** argv) {
studentList* list = NULL;
list = (studentList*) malloc(sizeof(studentList));
list->numberOfStudents =1;
//list->students->matrikelNummer = 1;
//strcpy(list->students->name , "karim");
printf("numberOfStudents : %d\n" , list->numberOfStudents );
//printf("matrikelNummer : %d\n" , list->students->matrikelNummer);
//printf("name : %d\n" , list->students->name);
free(list);
return 0;
}
That seems to work with no problems. But when I try to assign data to the students (matrikelNummer or name) as outlined in the commented lines, I receive a Segmentation fault.
What am I doing wrong?

Not allocated pointers
The problem is that you do:
// list points to null after that line
studentList* list = NULL;
// allocate memory for the list struct
list = (studentList*) malloc(sizeof(studentList));
// set field inside list struct
list->numberOfStudents =1;
// list->students is a pointer, but pointers should point to something valid
// So the question is: Was list->students set to NULL?
// Or was it mallocated?
list->students->matrikelNummer = 1;
So you access list->students that is a pointer.
List itself was allocated via malloc so its fine.
But malloc reserves space for only the list object you want.
It does not mallocate anything else.
So list->students is a pointer that is not mallocated - that's why we get the segmentation fault error.
Solution to this problem is pretty straightforward - we have to allocate not only a list but all pointers we use (in this case its students member):
// That was earlier there:
studentList* list = NULL;
list = (studentList*) malloc(sizeof(studentList));
// After allocating place for list also allocate place for list->students:
list->students = (student*) malloc(sizeof(student));
Detection of invalid memory usage
In a case when you get segmentation faults or memory leaks it's good to know that there are plenty of tools to help programmers detect such a nasty errors.
One of them is Valgrind
Valgrind is available for Linux (and probably for Windows but buggy and untested).
It's awesome tools that can traverse your program and notify you about any leaks, invalid frees and usage of forbidden memory addresses.
Example usage of Valgrind:
# Compile your code
gcc list.c -o list
# Use Valgrind
valgrind --tool=memcheck ./list
And what valgrind shows:
==26761== Memcheck, a memory error detector
==26761== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==26761== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==26761== Command: ./list
==26761==
==26761== Use of uninitialised value of size 8
==26761== at 0x4006A1: main (in /home/students/inf/p/ps386038/stack/list)
==26761==
==26761== Invalid write of size 4
==26761== at 0x4006A1: main (in /home/students/inf/p/ps386038/stack/list)
==26761== Address 0x40 is not stack'd, malloc'd or (recently) free'd
==26761==
==26761==
==26761== Process terminating with default action of signal 11 (SIGSEGV)
==26761== Access not within mapped region at address 0x40
==26761== at 0x4006A1: main (in /home/students/inf/p/ps386038/stack/list)
==26761== If you believe this happened as a result of a stack
==26761== overflow in your program's main thread (unlikely but
==26761== possible), you can try to increase the size of the
==26761== main thread stack using the --main-stacksize= flag.
==26761== The main thread stack size used in this run was 8388608.
==26761==
==26761== HEAP SUMMARY:
==26761== in use at exit: 16 bytes in 1 blocks
==26761== total heap usage: 1 allocs, 0 frees, 16 bytes allocated
==26761==
==26761== LEAK SUMMARY:
==26761== definitely lost: 0 bytes in 0 blocks
==26761== indirectly lost: 0 bytes in 0 blocks
==26761== possibly lost: 0 bytes in 0 blocks
==26761== still reachable: 16 bytes in 1 blocks
==26761== suppressed: 0 bytes in 0 blocks
==26761== Rerun with --leak-check=full to see details of leaked memory
==26761==
==26761== For counts of detected and suppressed errors, rerun with: -v
==26761== Use --track-origins=yes to see where uninitialised values come from
==26761== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
So it shows that you access invalid address in function main:
==26761== Invalid write of size 4
==26761== at 0x4006A1: main (in /home/students/inf/p/ps386038/stack/list)
==26761== Address 0x40 is not stack'd, malloc'd or (recently) free'd
And says the address (pointer is not even allocated)!
Correct C list implementation
If you want to implement a pointers structure that holds list of students
then one common approach is to put a pointer to the next student (next on the list) into the s_student structure.
And pointers to the first and last student into the student list.
One working example is the following I wrote myself:
#include <stdio.h>
#include <stdlib.h>
typedef struct s_student student;
struct s_student
{
char name[64];
int matrikelNummer;
// This will point to the next student on the list
student* nextStudent;
};
typedef struct s_studentList
{
student* student;
// This will point to the last available student
student* lastStudent;
// This will point to the first available student
student* firstStudent;
int numberOfStudents;
} studentList;
// Allocates the list
void allocStudentsList(studentList** list) {
if(list == NULL) return;
*list = (studentList*) malloc(sizeof(studentList));
(*list)->lastStudent = NULL;
(*list)->firstStudent = NULL;
}
// To add the student to the list
void addStudentToList(studentList* list, student studentData) {
if(list == NULL) return;
// Allocate a place for the next student
student* st = (student*) malloc(sizeof(student));
// If it's first student in the list
if(list->lastStudent == NULL) {
list->lastStudent = st;
list->firstStudent = st;
} else {
// The next student after the current last student will be the newly created one
list->lastStudent->nextStudent = st;
}
// Fill the student data
*st = studentData;
st->nextStudent = NULL;
// Set the last available student to the one created
list->lastStudent = st;
}
// To recurisvely free the students
void freeStudent(student* stud) {
if(stud->nextStudent != NULL) {
// Free next student recursively
freeStudent(stud->nextStudent);
}
free(stud);
}
// To free the students list
void freeStudentsList(studentList* list) {
if(list != NULL) {
freeStudent(list->firstStudent);
free(list);
}
}
// Function that prints single student and returns next one (after him on the list)
student* printStudent(student* stud) {
if(stud == NULL) return NULL;
printf(" * Student { matrikelNummer = %d }\n", stud->matrikelNummer);
// Return next student
return stud->nextStudent;
}
// Function that prints students list
void printStudentsList(studentList* list) {
if(list == NULL) return;
printf("StudentsList [\n");
student* current_student = list->firstStudent;
while(current_student != NULL) {
current_student = printStudent(current_student);
}
printf("]\n");
}
int main(int argc, char** argv) {
studentList* list = NULL;
allocStudentsList(&list);
// Create some student data
student st1;
st1.matrikelNummer = 1;
// Another student...
student st2;
st2.matrikelNummer = 2;
// Put them into the list (allocates students and take care of everything)
addStudentToList(list, st1);
addStudentToList(list, st2);
// Print the list
printStudentsList(list);
// Free the list (recursively free's all students and take care of all the nasty stuff)
freeStudentsList(list);
return 0;
}
There are plenty of tutorials how to write C-style lists structures on the web.
You can find one yourself.
One of the tutorial is there: Learn-c linked list tutorial

in your s_studentlist struct you have a pointer called students, you never used malloc on this member so its just a pointer to a random chunk in memory, allocate it the same way you did with your list variable

you need to allocate memory for the student. When using malloc you only allocate memory for the list type, which includes a pointer to a student-type but not memory for the student type:
studentList* list = NULL;
list = (studentList*) malloc(sizeof(studentList));
list->students = (student*) malloc(sizeof(student));
Another Problem with you list is that I don't know how it is designed to work.
A list normally contains a pointer to the next element:
typedef struct s_student {
struct s_student* next;
char name[64];
int matrikelNummer;
} student;
Another approach would be to store a list of students as an array in studentList, but hten you would need to allocate memory for more than one student:
list->students = (student*) malloc(list->numberOfStudents * sizeof(student));
This would be no list, but an array and you would access entries with
list->students[0].matrikelNummer

Related

Why am I getting "invalid read" and "invalid write" from valgrind with the following code?

I am writing a program to make sure I understand how to correctly implement a singly linked list in C. I'm currently in the middle of Harvard's CS50 course, and using this tutorial since the CS50 people don't explain the linked list data structure in a lot of detail: https://www.youtube.com/watch?v=7Fz7JSvlr9g
The code seems to function ok, but I am getting "invalid read" and "invalid write" errors when I check it using valgrind.
Here's my code:
// creating and using a singly linked list in C
#include <stdio.h>
#include <stdlib.h>
// create structure for nodes
typedef struct sllist
{
int val;
struct sllist *next;
}
sllnode;
// function declarations
sllnode *create(int sz);
void display(sllnode *head);
int main(void)
{
// declare head node and set to NULL
sllnode *head = NULL;
// prompt for size of list
printf("how many numbers would you like to store? ");
int sz;
scanf("%i", &sz);
// create linked list (create passes head pointer back to head)
head = create(sz);
// display linked list
display(head);
}
// function for creating a linked list
sllnode *create(int sz)
{
// initialize head pointer to NULL
sllnode *head = NULL;
// initialize temp pointer (for creating new nodes in the upcoming for loop)
sllnode *temp = NULL;
// initialize p for iterating through the list
sllnode *p = NULL;
for (int i = 0; i < sz; i++)
{
// allocate space for individual node
temp = (sllnode *)malloc(sizeof(sllnode));
// check to make sure we haven't run out of memory
if (temp == NULL)
{
printf("Couldn't allocate memory\n");
exit(1);
}
// prompt user for value to store
printf("enter the value #%i: ", i + 1);
scanf("%i", &(temp->val));
// intialize temp's next pointer to NULL
temp->next = NULL;
// if running first time (linked list is empty) temp becomes the head node
if (head == NULL)
{
head = temp;
}
// if the loop has run a few times (list not empty)
else
{
// start at the head
p = head;
// iterate through the list to find the last node
while (p->next != NULL)
{
p = p->next;
}
// set that node's pointer to the new node
p->next = temp;
}
free(temp);
}
// give the head pointer back to main
return head;
}
// function for displaying the linked list
void display(sllnode *head)
{
// initialize pointer p to head (coming from main)
sllnode *p = head;
// iterate through the list, printing a new value each time
while(p != NULL)
{
printf("%i -> ", p->val);
p = p->next;
}
printf("\n");
}
And here's the output from valgrind:
==4407== Memcheck, a memory error detector
==4407== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4407== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==4407== Command: ./ll0
==4407==
how many numbers would you like to store? 2
enter the value #1: 1
enter the value #2: 6
==4407== Invalid read of size 8
==4407== at 0x4209DA: create (ll0.c:74)
==4407== by 0x420713: main (ll0.c:29)
==4407== Address 0x6183048 is 8 bytes inside a block of size 16 free'd
==4407== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4407== by 0x420B73: create (ll0.c:81)
==4407== by 0x420713: main (ll0.c:29)
==4407==
==4407== Invalid write of size 8
==4407== at 0x420B65: create (ll0.c:79)
==4407== by 0x420713: main (ll0.c:29)
==4407== Address 0x6183048 is 8 bytes inside a block of size 16 free'd
==4407== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4407== by 0x420B73: create (ll0.c:81)
==4407== by 0x420713: main (ll0.c:29)
==4407==
==4407== Invalid read of size 4
==4407== at 0x420CAA: display (ll0.c:96)
==4407== by 0x420720: main (ll0.c:31)
==4407== Address 0x6183040 is 0 bytes inside a block of size 16 free'd
==4407== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4407== by 0x420B73: create (ll0.c:81)
==4407== by 0x420713: main (ll0.c:29)
==4407==
1 -> ==4407== Invalid read of size 8
==4407== at 0x420D62: display (ll0.c:97)
==4407== by 0x420720: main (ll0.c:31)
==4407== Address 0x6183048 is 8 bytes inside a block of size 16 free'd
==4407== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4407== by 0x420B73: create (ll0.c:81)
==4407== by 0x420713: main (ll0.c:29)
==4407==
6 ->
==4407==
==4407== HEAP SUMMARY:
==4407== in use at exit: 0 bytes in 0 blocks
==4407== total heap usage: 2 allocs, 2 frees, 32 bytes allocated
==4407==
==4407== All heap blocks were freed -- no leaks are possible
==4407==
==4407== For counts of detected and suppressed errors, rerun with: -v
==4407== ERROR SUMMARY: 6 errors from 4 contexts (suppressed: 0 from 0)
Seems like it has something to do with the way I'm accessing the temp node, but I don't really understand the issue.
Because in the create function you free the nodes you just have added to the list.
Simply remove the free(temp); from the function.
The variable name temp is misleading here. It is not at all a temporary node. A correct name for this variable would be newnode.
You should read again the chapter dealing with dynamic memory allocation in your C text book.
Note 1: BTW: In the video you mention there is no free in the create function.
Note 2: Be aware that this algorithm for creating the list is terribly inefficient. In order to find the last element, the whole list is traverses from the head to the last element. In order to be efficient you should maintain the pointer to the last element.

Valgrind detects reachable leaks, where are they?

I have written a small implementation of a simple stack in C using a linked list. The application works after a bit of fussing with gdb and valgrind. However, I have noticed that valgrind reports a number of "still reachable" leaks at termination of the program.
After some googling, I have found that these type of leaks are not an issue and that I generally shouldn't worry about them. Well that's great news! The only thing is, I would REALLY like to understand why valgrind sees these leaks and where they appear. I went to great pains through my first pass at this application to diligently release any allocated memory. What did I miss? Where are these allocations that valgrind sees but I cannot?
I have been staring at this for awhile now, and despite fiddling with the code this way and that, have come up empty handed. Hopefully you all can help me in this endeavor.
I have stripped the app down to a minimal example that will present the leak I am observing. It just initializes the stack and then immediately destroys it and exits.
// simple stack implementation
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
/*--- data structure in a stack item ---*/
struct data {
char * message;
};
/*--- stack item structure ---*/
struct item {
struct data * my_data;
struct item * next;
};
/*--- stack data structure ---*/
struct stack {
int initialized;
int empty;
struct item * head;
};
struct stack * my_stack;
/*--- create a new stack data structure with provided initial data ---*/
int
create_stack(struct data ** initial_items, int num_items) {
//allocate memory for the stack structure itself
my_stack = (struct stack *) malloc(sizeof(struct stack));
if(!my_stack) return -1;
my_stack->empty = 1;
my_stack ->initialized = 0;
if(num_items) {
//allocate memory for the head of the list first
my_stack->head = (struct item *) malloc(sizeof(struct item));
if(!my_stack->head) return -1;
my_stack->head->my_data = initial_items[0];
my_stack->head->next = NULL;
struct item * tracker = my_stack->head;
//fill the stack with elements containing the provided data
int i = 1;
for(; i < (num_items); i++) {
tracker->next = (struct item *) malloc(sizeof(struct item));
tracker = tracker->next;
if(!tracker) return -1;
tracker->my_data = initial_items[i];
tracker->next = NULL;
}
//no longer empty
my_stack->empty = 0;
}
//set initialized flag & return
my_stack->initialized = 1;
return 0;
}
/*--- destroy the stack by recursively freeing nodes ---*/
int
destroy_stack(struct item * recurse) {
//if the starting node is valid, begin
if(recurse) {
//if the current node links to another
if(recurse->next)
//recurse on the next node
destroy_stack(recurse->next);
else
//otherwise we hit the end, free the node
free(recurse);
}
//the starting node is invalid, just free the stack itself
else {
free(my_stack);
}
return 0;
}
/*--- test wrapper ---*/
int
main(int argc, char **argv) {
//initialize 10 element list of data structures to fill the stack items with
int i = 0;
int length = 10;
struct data ** initial_values = (struct data **) malloc(length*sizeof(struct data *));
//set each data element's value to i
for(; i < length; i++) {
char temp[16];
sprintf(temp, "%d", i);
initial_values[i] = (struct data *) malloc(sizeof(struct data));
initial_values[i]->message = strdup(temp);
}
//simple test case
//create a stack with the generated initial data, then destroy it
assert( !create_stack(initial_values, length) );
assert( !destroy_stack(my_stack->head) );
//free the string data our stack nodes were pointing to
i = 0;
while(i < length) {
free(initial_values[i]->message);
free(initial_values[i]);
i += 1;
}
free(initial_values);
return 0;
}
Running this through valgrind produces the following identified, unreleased blocks:
(trusty)kin3tix#localhost:~/C Practice/Data Structures$ valgrind --leak-check=full --show-leak-kinds=all ./stack_leak_test
==19340== Memcheck, a memory error detector
==19340== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==19340== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==19340== Command: ./stack_leak_test
==19340==
==19340==
==19340== HEAP SUMMARY:
==19340== in use at exit: 168 bytes in 10 blocks
==19340== total heap usage: 32 allocs, 22 frees, 364 bytes allocated
==19340==
==19340== 16 bytes in 1 blocks are still reachable in loss record 1 of 3
==19340== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19340== by 0x400739: create_stack (stack_leak_test.c:40)
==19340== by 0x40093B: main (stack_leak_test.c:95)
==19340==
==19340== 24 bytes in 1 blocks are still reachable in loss record 2 of 3
==19340== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19340== by 0x4006E6: create_stack (stack_leak_test.c:33)
==19340== by 0x40093B: main (stack_leak_test.c:95)
==19340==
==19340== 128 bytes in 8 blocks are still reachable in loss record 3 of 3
==19340== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19340== by 0x4007A1: create_stack (stack_leak_test.c:48)
==19340== by 0x40093B: main (stack_leak_test.c:95)
==19340==
==19340== LEAK SUMMARY:
==19340== definitely lost: 0 bytes in 0 blocks
==19340== indirectly lost: 0 bytes in 0 blocks
==19340== possibly lost: 0 bytes in 0 blocks
==19340== still reachable: 168 bytes in 10 blocks
==19340== suppressed: 0 bytes in 0 blocks
==19340==
==19340== For counts of detected and suppressed errors, rerun with: -v
==19340== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
They all seem to stem from "create_stack" but as far as I can tell my destroy function should be catching everything I allocate. What am I missing here?
Your destruction logic is trying to recursively combine two tasks (deleting the stack object and its items) in a single function. Worse, the else state shouldn't be there at all. You already determined you're sitting on a dynamic node (recurse). It needs to be deleted. Whether it has a next or not is not for the current depth to decide; that will be taken care of in the next depth of recursion.
Honestly, this is much simpler if you create a helper to wipe out the linked list, and as separate wrapper to do said-same to the stack itself:
/*--- destroy linked list nodes recursively ---*/
static void destroy_stack_items(struct item *item)
{
if (item)
{
destroy_stack_items(item->next);
free(item);
}
}
/*--- destroy the stack by recursively freeing nodes ---*/
int destroy_stack(struct stack *s)
{
if (s)
{
destroy_stack_items(s->head);
free(s);
}
return 0
}
and simply invoked as:
destroy_stack(my_stack);
Personally I would do it iteratively (thus remove the helper in the process), but I'm sure you have your reasons for otherwise. For example:
/*--- destroy the stack by iteratively freeing nodes ---*/
int destroy_stack(struct stack *s)
{
if (s)
{
while (s->head)
{
struct item *tmp = s->head;
s->head = tmp->next;
free(tmp);
}
free(s);
}
return 0
}
Best of luck.

C - Receiving a SIGABRT when freeing structs - System-specific?

I'm currently tinkering with binary trees in C, but I've run into an issue that I can't seem to solve on my own. I'm using Eclipse Mars as my IDE.
The basic idea of the project is to have a binary tree composed out of treeNodes. These nodes are structs and contain a struct within (struct Books), thus there are two separate libs for treeNode and books.
These are the structs in question:
TreeNode:
struct TreeNode {
struct Book *book;
unsigned long key;
struct TreeNode *left;
struct TreeNode *right;
};
Book:
struct Book {
unsigned long ISBN;
char* author_name;
char* book_title;
};
Now, the nodes get created fine and the insertion/print functions work well. However, I also have a clear() function, that is supposed to free any previously allocated memory. Malloc is called only in the new_xxx() functions:
struct TreeNode *new_tree_node(unsigned long ISBN, char *author, char *title) {
//Creating and allocating the new TreeNode
struct TreeNode *new_tree_node;
new_tree_node = (struct TreeNode*) malloc(sizeof(struct TreeNode));
//Creating the book
struct Book *new_Book = newBook(ISBN, author, title);
new_tree_node->book = new_Book;
new_tree_node->left = NULL;
new_tree_node->right = NULL;
new_tree_node->key = ISBN;
return new_tree_node;
}
And newBook():
struct Book *newBook(unsigned long ISBN_nr, char *author_name, char *book_title) {
//Creating and allocating the Book
struct Book *new_Book;
new_Book = (struct Book*) malloc(sizeof(struct Book));
//Assigning Values
new_Book->ISBN = ISBN_nr;
new_Book->author_name = author_name;
new_Book->book_title = book_title;
return new_Book;
}
Now, when I try to run the clear() function, I receive a "SIGABRT:Aborted" signal as soon as I try to free a TreeNode and the process halts. Eclipse also returns:
"No source available for "raise() at 0x75ffff7a4bcc9".
Initially I thought this happened because my system could not find one of the standard functions, but the console also prints:
*** Error in /home/max/workspace/bst_2/Debug/bst_2': double free or corruption (out): 0x00007fffffffe030 ***
which makes me believe that there actually is an issue within the code.
This is the function in question:
void bst_clear(struct TreeNode *tree_node) {
//Clears all nodes recursively
if (tree_node->left != NULL) {
bst_clear(tree_node->left);
}
if (tree_node->right != NULL) {
bst_clear(tree_node->right);
}
tree_node->key = NULL;
tree_node->book = NULL;
free((void*) tree_node);
return;
}
Funny thing is, this does only happen while using a Linux OS (Mint 17.1) - both in a VM and as a dual-boot system. My main OS, which is Windows 7 64-bit, does compile and run without any issues and gets through the process entirely.
I am not sure whether something is actually wrong with the code (which could definitely be the case, I'm still a newbie) or whether my OS did mess something up there. But since this happened both in a VM and an actual system, it probably has nothing to do with missing system libraries (I guess).
So, does anyone have a clue on what's going on here?
EDIT: valgrind output:
==2946== Invalid free() / delete / delete[] / realloc()
==2946== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2946== by 0x4008D3: bst_clear (booktree.c:84)
==2946== by 0x400884: bst_clear (booktree.c:73)
==2946== by 0x400884: bst_clear (booktree.c:73)
==2946== by 0x400D17: main (main.c:66)
==2946== Address 0xfff000030 is on thread 1's stack
==2946==
==2946== Invalid free() / delete / delete[] / realloc()
==2946== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
...
==2946==
==2946==
==2946== HEAP SUMMARY:
==2946== in use at exit: 128 bytes in 4 blocks
==2946== total heap usage: 10 allocs, 10 frees, 280 bytes allocated
==2946==
==2946== LEAK SUMMARY:
==2946== definitely lost: 128 bytes in 4 blocks
==2946== indirectly lost: 0 bytes in 0 blocks
==2946== possibly lost: 0 bytes in 0 blocks
==2946== still reachable: 0 bytes in 0 blocks
==2946== suppressed: 0 bytes in 0 blocks
==2946== Rerun with --leak-check=full to see details of leaked memory
The error appeared multiple times - the line in question is the free() command - line 73 is just the recursive function call.
Now, if I got this right, I'm trying to free an object in the stack - read-only memory, right? The only thing I can think of are the struct declarations, which contain possibly static elements?
I'd also like to point out, that there is ZERO issue when running this on a Windows machine - does anyone know the reason for this?
EDIT 2:
This is how nodes are created:
char* root_author;
char* root_title;
root_author = "A B C\0";
root_title = "ABC\0";
struct TreeNode *root;
root = new_tree_node(579610, root_author, root_title);
char* n1a;
char* n1t;
n1a = "B C D";
n1t = "BCD";
struct TreeNode *n1 = new_tree_node(406759, n1a, n1t);
bst_insert(root, n1);
And this is the insert() function:
void bst_insert(struct TreeNode *tree_node, struct TreeNode *new_node) {
if (new_node->key < tree_node->key) {
//If the key is smaller -> insert left
if (tree_node->left == NULL) {
//There is no left node yet
tree_node->left = new_node;
return;
} else
bst_insert(tree_node->left, new_node); //There is a node -> pass it on
}
else {
//The key is larger -> right
if (tree_node->right == NULL) {
//There is no left node yet
`enter code here`tree_node->right = new_node;
return;
} else
bst_insert(tree_node->right, new_node); //There is a node -> pass it on
}
}

Linked list :: hash table :: Valgrind error :: Conditional jump or move depends on uninitialised value

Need help again.
I've got my linked list working. It copies a list of words from a file into a linked list.
Now I want to make a hash table so that all words starting with the letter 'A' go into a bucket [0] of linked list.
The code I've written; it seems to work for small and large lists but Valgrind shows points to errors.
-----CODE-----
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct node //struct for linked list
{
char* word;
struct node* next;
}
node;
int findhash(char firstletter) //this function returns a hash value for first alphabet of every word
{
int hash = 0;
if(isupper(firstletter))
hash = firstletter-'A';
else hash = firstletter-'a';
return hash;
}
int main (void)
{
char* dictfile = "small";
FILE* dict = fopen(dictfile, "r");
if (dict == NULL)
return 1;
char oneword[47]; //to store the word from fscanf()
node* hashtable [30]; //creates a hashtable
for (int i = 0; i < 30; i++) //gives an index to every element in the hash table
{
node* temp = (node*)malloc(sizeof(node));
temp->next = NULL;
hashtable[i] = temp;
}
while ((fscanf (dict, "%s", oneword)) > 0)
{
node* temp = (node*)malloc(sizeof(node));
char* tempword = (char*)malloc(strlen(oneword)+1); //gives me a new pointer to store the string (as pointed out by Antione)
strcpy(tempword, oneword);
char firstletter = tempword[0];
int hash = 0;
hash = findhash(firstletter); //returns an index for the first alphabet of the word
temp->word = tempword;
//printf("%s\n", temp->word); //prints the value (just for debug)
temp->next = hashtable[hash];
hashtable[hash] = temp;
}
for (int i = 0; i < 30; i++)
{
node* temp = (node*)malloc(sizeof(node));
temp = hashtable[i];
while (temp != NULL) //loop to print the linked list
{
if (temp->word != NULL) //**THIS IS WHERE VALGRIND IS POINTING THE ERROR TO BE**
{
printf("%s\n", temp->word);
temp = temp->next;
}
else break;
}
}
printf("\n");
fclose(dict);
printf("SUCCESS!!\n");
}
Where am I going wrong?? Please help
-----VALGRIND ERROR-----
jharvard#appliance (~/Dropbox/pset5): valgrind ./tempeol
==11035== Memcheck, a memory error detector
==11035== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==11035== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==11035== Command: ./tempeol
==11035==
antione
==11035== Conditional jump or move depends on uninitialised value(s)
==11035== at 0x80488CA: main (tempeol.c:68)
==11035==
beer
bear
caterpillar
cat
google
root
SUCCESS!!
==11035==
==11035== HEAP SUMMARY:
==11035== in use at exit: 582 bytes in 74 blocks
==11035== total heap usage: 75 allocs, 1 frees, 934 bytes allocated
==11035==
==11035== LEAK SUMMARY:
==11035== definitely lost: 480 bytes in 60 blocks
==11035== indirectly lost: 102 bytes in 14 blocks
==11035== possibly lost: 0 bytes in 0 blocks
==11035== still reachable: 0 bytes in 0 blocks
==11035== suppressed: 0 bytes in 0 blocks
==11035== Rerun with --leak-check=full to see details of leaked memory
==11035==
==11035== For counts of detected and suppressed errors, rerun with: -v
==11035== Use --track-origins=yes to see where uninitialised values come from
==11035== ERROR SUMMARY: 30 errors from 1 contexts (suppressed: 0 from 0)
Valgrind shows 30 errors. My hashtable is size 30. So feel the problem should be somewhere there. But I can't figure out why?
Your initialization of the hashtable entries isn't initializing the field word, that is what valgrind is complaining about.
Additionally your code seems to have other problems. E.g the malloc in the line just before is immediately overwritten and thus this memory leaks. Also the return of malloc shouldn't be cast. Avoid casts whenever you can, think of casts as "casting a spell". As long as you don't know what that does, avoid it.

Freeing memory in a function

I'm writing a simple program in C that finds anagrams of words based on looking them up in a hash table. What I have is an array of hash tables, where words are indexed by their length and hashed within by the summation of their letters, e.g. a = 1, b = 2, etc.
I'm still getting acquainted with dynamic memory management in C, so this question may be quite simple, but I have a functions that allocate and deallocate memory for each hash table (and its inside data).
I originally wrote this program using a single hash table and after running the program through valgrind I found that the memory had been freed correctly and there were no leaks. However, when expanding the program to use an array of hash tables, valgrind began to find possible leaks (though it's reporting them as still reachable). I'm confused as to why the memory isn't being freed correctly in the array of hash tables, although each hash table in the array is being run through the deallocate function that was used originally.
Gist with the full code Full Code
typedef struct Bucket Bucket;
typedef struct HashTable HashTable;
struct Bucket {
char* data;
Bucket *next;
};
struct HashTable {
int size;
Bucket **buckets;
};
int main(int argc, char const *argv[])
{
// Allocate memory for array of hash tables
HashTable** hash_array = (HashTable**) malloc(sizeof(HashTable*) * WORD_SIZE);
for(i = 0; i < WORD_SIZE; i++) {
hash_alloc(&hash_array[i], BUCKET_COUNT);
}
// Main logic here...
// Free memory
for(i = 0; i < WORD_SIZE; i++) {
hash_dealloc(hash_array[i]);
}
free(hash_array);
return 0;
}
Hash Table Allocation function
void hash_alloc(HashTable** a, unsigned int size) {
*a = (HashTable*) malloc(sizeof(HashTable));
(*a)->buckets = (Bucket**) malloc(sizeof(Bucket*) * size);
(*a)->size = size;
}
Hash Table Deallocation function
void hash_dealloc(HashTable* a) {
int i;
Bucket* current, *temp;
for(i = 0; i < a->size; i++) {
current = a->buckets[i];
while(current != NULL) {
temp = current;
free(temp->data);
current = current->next;
free(temp);
}
free(current);
}
free(a->buckets);
free(a);
}
Add to hash table function
void add_to_hash_array(HashTable** a, char* data) {
// Removed some other logic for readability...
replace_str(data, "\n", "\0");
newNode->data = strdup(data);
newNode->next = currentTable->buckets[index];
currentTable->buckets[index] = newNode;
} else {
return;
}
}
Valgrind output
==39817== 261,120 bytes in 128 blocks are still reachable in loss record 5 of 7
==39817== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==39817== by 0x400A38: hash_alloc (main.c:73)
==39817== by 0x4008B0: main (main.c:39)
==39817==
==39817== 286,936 bytes in 31,553 blocks are still reachable in loss record 6 of 7
==39817== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==39817== by 0x4EBAD71: strdup (strdup.c:43)
==39817== by 0x400D4D: add_to_hash_array (main.c:141)
==39817== by 0x400914: main (main.c:51)
==39817==
==39817== 504,848 bytes in 31,553 blocks are still reachable in loss record 7 of 7
==39817== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==39817== by 0x400D16: add_to_hash_array (main.c:136)
==39817== by 0x400914: main (main.c:51)
In generate_anagrams
void generate_anagrams(HashTable* a, char* word) {
int index = hash(word);
char* word_dup = strdup(word);
char* current_word;
string_sort(word_dup);
printf("%s: %i size: %zi\n", word, index, strlen(word));
Bucket* current = a->buckets[index];
while(current != NULL) {
if(current->data) {
current_word = strdup(current->data);
string_sort(current_word);
if(strcmp(word_dup, current_word) == 0) {
printf("%s\n", current->data);
}
}
current = current->next;
}
free(current_word);
free(word_dup);
}
you are leaking thestrduped current_words. Move the free(current_word); into the if (current->data).
In add_to_hash_array
void add_to_hash_array(HashTable** a, char* data) {
int index = hash(data);
HashTable* currentTable = a[strlen(data)];
Bucket* existingNode = hash_lookup(currentTable, data);
if(existingNode == NULL) {
Bucket *newNode = (Bucket*) malloc(sizeof(Bucket));
if(newNode == NULL) {
exit(1);
}
replace_str(data, "\n", "\0");
newNode->data = strdup(data);
newNode->next = currentTable->buckets[index];
currentTable->buckets[index] = newNode;
} else {
return;
}
}
You only remove the newline from data after you have looked it up, but you insert data after removing the newline, so you will not detect duplicates.
In main, you should not
generate_anagrams(hash_array[strlen(arg_dup) + 1], arg_dup);
but use hash_array[strlen(arg_dup)] if you remove the newline right at the beginning of add_to_hash_array.
And of course, you should ensure that hash generates no out-of-range indices.
And strncpy(str, str, p-str); is undefined behaviour.
Moving my comment to an answer because this nearly works.
No need to initialise to NULL before malloc, but any variable pointers that you later free should be set to NULL and only free if not NULL. Also initialise pointer values in your structs to NULL (easier to use calloc and get this automatically) so your guards work properly. I've had a bit more of look over your code and your hashing worries me - you need to make sure your hash function only returns values in the range 0 to BUCKET_COUNT-1. I made a few quick changes of this kind, and fixed your replace_str method and it no longer complains with valgrind.
Now when I run the code I see it finding the correct words to compare with, but the sorting function is not returning a sorted string, so it is not identifying the anagrams. Should be an easy fix.
Edit: I just pasted in the first string sort routine a google search found for me and ran to get the following output:
./a.out trips
trips: 82 size: 5
strip
stirp
sprit
spirt
Ther's no memory leak, but the code has some problems (the replace_str function need to be replaced by a correct version). The output of valgrind on my linux box:
$ valgrind --leak-check=full --show-reachable=yes ./MEMORY_LEAK absurde
==13476== Memcheck, a memory error detector
==13476== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==13476== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
==13476== Command: ./MEMORY_LEAK absurde
==13476==
==13476== Conditional jump or move depends on uninitialised value(s)
==13476== at 0x8048A9A: hash_lookup (MEMORY_LEAK.c:132)
==13476== by 0x80489BD: add_to_hash_array (MEMORY_LEAK.c:113)
==13476== by 0x804871C: main (MEMORY_LEAK.c:50)
==13476==
absurde: 70 size: 7
==13476== Conditional jump or move depends on uninitialised value(s)
==13476== at 0x8048D1C: generate_anagrams (MEMORY_LEAK.c:169)
==13476== by 0x8048795: main (MEMORY_LEAK.c:56)
==13476==
==13476== Conditional jump or move depends on uninitialised value(s)
==13476== at 0x8048890: hash_dealloc (MEMORY_LEAK.c:81)
==13476== by 0x80487D8: main (MEMORY_LEAK.c:64)
==13476==
==13476== Conditional jump or move depends on uninitialised value(s)
==13476== at 0x4027BC2: free (vg_replace_malloc.c:366)
==13476== by 0x804889C: hash_dealloc (MEMORY_LEAK.c:87)
==13476== by 0x80487D8: main (MEMORY_LEAK.c:64)
==13476==
==13476==
==13476== HEAP SUMMARY:
==13476== in use at exit: 0 bytes in 0 blocks
==13476== total heap usage: 360 allocs, 360 frees, 133,424 bytes allocated
==13476==
==13476== All heap blocks were freed -- no leaks are possible
==13476==
==13476== For counts of detected and suppressed errors, rerun with: -v
==13476== Use --track-origins=yes to see where uninitialised values come from
==13476== ERROR SUMMARY: 65330 errors from 4 contexts (suppressed: 11 from 6)

Resources