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
}
}
Related
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.
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
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
A segmentation fault occurs after everything has been executed. I tried for hours but still can't find the problem. I feel depressed and any assistance is appreciated!
All the code are under directory "KNN - GitHub" in this link: https://ide.c9.io/captainzidane/kd_tree
point.txt, test2.c, kdtree.c, kdtree.h are to be used.
Here is part of my "test.c" file, where the seg fault occurs at the last line. i.e., the last closing brace }
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include "kdtree.h"
#define DEF_NUM_PTS 10
#define MAX_NUM_OF_POINTS 20000
#define DIMENSION 3
int main (int argc, char *argv[]) {
//int arraySize;
double pointArray[MAX_NUM_OF_POINTS][DIMENSION];
FILE *coordFile = fopen ("points.txt", "r");
//coord *coords = malloc(sizeof(coord) * MAX_NUM_OF_POINTS);
int lineCounter = 0;
while (fscanf (coordFile, "%lf %lf %lf", &pointArray[lineCounter][0], &pointArray[lineCounter][1],
&pointArray[lineCounter][2]) == 3 && lineCounter < MAX_NUM_OF_POINTS) {
lineCounter++;
}
double range = 8.1;
int num_of_nearest;
double queryPoint[DIMENSION];
int counter;
int dist;
int num;
//scanf ("%lf %lf %lf %d", &queryPoint[0], &queryPoint[1], &queryPoint[2], &num);
queryPoint[0] = 1;
queryPoint[1] = 5;
queryPoint[2] = 8;
num = 10;
//Build and insert points to a KD Tree
struct kdtree *newTree = buildTree (pointArray);//////make it run only once
//Return nearst N nodes and distance in order from smallest to largest
struct knn_result *res_n = knn(newTree, queryPoint, num);
free (res_n);
printf ("======================================================\n");
//Return nodes within a range of the query point
struct nn_range *res_range = nn_range(newTree, queryPoint, range);
free (res_range);
printf ("======================================================\n");
fclose (coordFile);
kd_free(newTree);///To be deleted
return EXIT_SUCCESS;
}
Here is the part of my "kdtree.c" file which contains the function which may cause the error:
struct nn_range {
double nearestRange[MAX_NUM_OF_POINTS][DIMENSION+1];
int nPoints;
};
struct nn_range *nn_range (struct kdtree *tree, const double *queryPoint, double range)
{
printf ("Nodes within a radius of %.3f to the query point:\n", range);
printf ("-------------------------------------------------\n");
struct kdres *presults_range = kd_nearest_range(tree, queryPoint, range);
double temp[3] = {0};
double dist_temp = 0;
struct nn_range *res = malloc(sizeof(struct nn_range));
int counter = 0,i;
res->nPoints = kd_res_size(presults_range);
printf("found %d results within the radius of %.3f\n", res->nPoints, range);
while(!kd_res_end( presults_range) && counter < res->nPoints)
{
dist_temp = 0;
/* get the data and position of the current result item */
kd_res_item(presults_range, temp);
/* compute the distance of the current result from the pt */
for(i=0; i<DIMENSION; i++)
{
dist_temp += SQ(queryPoint[i] - temp[i]);
}
dist_temp = sqrt(dist_temp);
res->nearestRange[counter][0] = temp[0];
res->nearestRange[counter][1] = temp[1];
res->nearestRange[counter][2] = temp[2];
res->nearestRange[counter][3] = dist_temp;
/* print out the retrieved data */
printf("node at (%.3f, %.3f, %.3f) is %.3f away\n", res->nearestRange[counter][0],
res->nearestRange[counter][1],
res->nearestRange[counter][2],
res->nearestRange[counter][3]);
/* go to the next entry */
kd_res_next(presults_range);
counter++;
}
kd_res_free(presults_range);
return res;
}
GDB said
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400ab9 in main (argc=1, argv=0x7fffffffe1d8) at test2.c:117
117 }
Valgrind said
==5369== Jump to the invalid address stated on the next line
==5369== at 0x3FE970FD6F3D35D2: ???
==5369== by 0x3FED48EE17391B6D: ???
==5369== by 0xFFF000157: ???
==5369== by 0xFFFFFFFF: ???
==5369== by 0x4008BC: ??? (in /home/ubuntu/workspace/KNN - GitHub/c)
==5369== Address 0x3fe970fd6f3d35d2 is not stack'd, malloc'd or (recently) free'd
==5369==
==5369==
==5369== Process terminating with default action of signal 11 (SIGSEGV)
==5369== Bad permissions for mapped region at address 0x3FE970FD6F3D35D2
==5369== at 0x3FE970FD6F3D35D2: ???
==5369== by 0x3FED48EE17391B6D: ???
==5369== by 0xFFF000157: ???
==5369== by 0xFFFFFFFF: ???
==5369== by 0x4008BC: ??? (in /home/ubuntu/workspace/KNN - GitHub/c)
==5369==
==5369== HEAP SUMMARY:
==5369== in use at exit: 0 bytes in 0 blocks
==5369== total heap usage: 40,057 allocs, 40,057 frees, 2,561,888 bytes allocated
==5369==
==5369== All heap blocks were freed -- no leaks are possible
==5369==
==5369== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==5369==
==5369== 1 errors in context 1 of 1:
==5369== Jump to the invalid address stated on the next line
==5369== at 0x3FE970FD6F3D35D2: ???
==5369== by 0x3FED48EE17391B6D: ???
==5369== by 0xFFF000157: ???
==5369== by 0xFFFFFFFF: ???
==5369== by 0x4008BC: ??? (in /home/ubuntu/workspace/KNN - GitHub/c)
==5369== Address 0x3fe970fd6f3d35d2 is not stack'd, malloc'd or (recently) free'd
==5369==
==5369== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault
Here is part of the output
Nodes within a radius of 8.100 to the query point:
-------------------------------------------------
found 24 results within the radius of 8.100
node at (0.718, 0.958, 0.994) is 8.093 away
node at (0.716, 0.974, 0.992) is 8.087 away
node at (0.629, 0.960, 0.991) is 8.099 away
node at (0.629, 0.960, 0.991) is 8.099 away
node at (0.556, 0.994, 0.979) is 8.096 away
node at (0.677, 0.985, 0.991) is 8.084 away
node at (0.556, 0.994, 0.979) is 8.096 away
node at (0.677, 0.985, 0.991) is 8.084 away
node at (0.909, 0.966, 0.980) is 8.097 away
node at (0.909, 0.966, 0.980) is 8.097 away
node at (0.909, 0.966, 0.980) is 8.097 away
node at (0.909, 0.966, 0.980) is 8.097 away
node at (0.978, 0.958, 0.993) is 8.089 away
node at (0.978, 0.958, 0.993) is 8.089 away
node at (0.978, 0.958, 0.993) is 8.089 away
node at (0.978, 0.958, 0.993) is 8.089 away
node at (0.857, 0.970, 0.978) is 8.098 away
node at (0.862, 0.985, 0.984) is 8.085 away
node at (0.862, 0.985, 0.984) is 8.085 away
node at (2.000, 2.000, 2.000) is 6.782 away
node at (2.000, 2.000, 2.000) is 6.782 away
node at (1.000, 1.000, 1.000) is 8.062 away
node at (1.000, 1.000, 1.000) is 8.062 away
node at (1.000, 2.000, 2.000) is 6.708 away
======================================================
Segmentation fault
A segmentation fault occurs after everything has been executed
In 99.9% of the cases this happens because you overflow a stack buffer allocated in main, and step on (corrupt) mains return address, so it returns to a "garbage" address.
I tried for hours but still can't find the problem
There are a few ways to find such problems:
Code inspection. Now that you know what to look for, examine all stack buffers in main, and check that you don't write to any of them out of bounds.
Allocate an extra buffer of 256 bytes before your first stack buffer in main, and after the last such buffer. Fill these extra buffers with a known sentinel value, and verify that the sentinel values are still intact just before returning from main. They likely wouldn't be. Once you know which sentinel value is getting corrupted, use GDB watchpoint to find which code writes to that address.
Valgrind (which you have tried) is very weak at detecting stack overflows. You could convert some of your stack buffers to be heap-allocated, and Valgrind will tell you right away where the overflow happened.
If you have a relatively recent compiler, both Clang and GCC support Address Sanitizer (-fsanitize=address), which is excellent at detecting both heap and stack overflows, and will likely point you straight at the problem.
All the code are under directory "KNN - GitHub"
That site requires a login. You don't seriously believe we all are going to sign up for an account there just so we can tell you exactly what the problem is? Next time, try to put your code somewhere more easily accessible.
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.
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.