C program is taking a branch even though it shouldn't - c

I have written a C program that constructs a binary search tree from an array. It goes through the following steps:
1: Sort the array with qsort().
2: Place the sorted elements of the array into a binary tree using the recursive function treeify():
2a: Take the middle element of the array (by dividing its length by 2) and place that as the content field of the tree struct (the root node of this subtree).
2b: Function then copies the left and right halves of the remaining elements into smaller arrays and calls itself for each of these arrays respectively.
2c: Return the tree via the root node.
3: Recursively traverse the tree and print its contents in indented format.
Basically, I used a divide-and-conquer paradigm to build the tree from the already-sorted array. Surprisingly (since this was my first time designing a D&C algorithm) this part went rather smoothly.
Where I really ran into trouble was in Step 3. Sometimes it works, and when it does, all of the elements are in the right order, so that part obviously works. But 90% of times I run the program, it segfaults when it gets to the first leaf node.
Here is the full program text. I've altered the printing function so that it prints the addresses of the nodes (for debugging purposes). Originally it displayed the numeric values...
#include <stdio.h>
#include <stdlib.h>
struct tree {
int content;
struct tree *left;
struct tree *right;
};
struct tree *treeify( int *, size_t );
void printtree( struct tree *, int );
int comp( int *, int * );
int main( int argc, char **argv ){
int array[] = { 5, 6, 7, 2, 3, 4, 9, 1, 8, 0 };
/* Sort array */
qsort( (void *) array, 10, sizeof( int ), (int (*)(const void *, const void *)) &comp );
for( int i = 0; i < 10; i++ ){
printf( "%d ", array[i] );
}
printf( "\n" );
/* Treeify array */
struct tree *rootnode = treeify( array, 10 );
/* Print tree */
printtree( rootnode, 0 );
return 0;
}
// Place sorted array elements in a tree
// Function is called for each subtree
struct tree *treeify( int *array, size_t size ){
struct tree *root = (struct tree *) malloc( sizeof( struct tree ) );
size_t middle = size/2;
int leftsize = middle, rightsize = size-middle-1;
int left[leftsize], right[rightsize];
for( int i = 0; i < leftsize; i++ ) left[i] = array[i];
for( int i = 0; i < rightsize; i++ ) right[i] = array[i+middle+1];
root->content = array[middle];
if( leftsize > 0 ) root->left = treeify( left, leftsize );
if( rightsize > 0 ) root->right = treeify( right, rightsize );
return root;
}
// Print tree contents in indented format
void printtree( struct tree *node, int level ){
for( int i = 0; i < level; i++ ) printf( " " );
printf( "%x\n", &(node->content) );
if( node->left ) printtree( node->left, level+1 );
if( node->right ) printtree( node->right, level+1 );
}
// Comparison function for qsort
int comp( int *xp, int *yp ){
int x = *xp, y = *yp;
if( x < y ) return -1;
if( x > y ) return 1;
return 0;
}
I've managed to isolate the problem by printing the addresses of the nodes when traversing the tree. Here is the output from a successful run:
0 1 2 3 4 5 6 7 8 9
cbe00000
cbe00020
cbe00040
cbe00060
cbe00080
cbe000a0
cbe000c0
cbe000e0
cbe00100
cbe00120
And an unsuccessful run:
f04032b0
f04032d0
f04032f0
f0403310
0
Segmentation fault: 11
Notice how the successful run only goes through three levels of the tree before returning and going back up. The unsuccessful run goes through four levels, reaching a null pointer.
Specifically, when the program gets to this line:
if( node->left ) printtree( node->left, level+1 );
It takes the branch despite node->left evaluating to zero (as indicated by the fifth line of the output).
This is what I can't for the life of me understand. The condition is clearly evaluating to false (I've verified that), and yet the program is still taking that branch as if it evaluated to true (and only in most, not all, cases).
This has literally never happened to me before. I'll need someone who knows a lot more about C than I do to shed some light on this for me.
The only possibilities I can think of:
Some quirky compiler optimization
I made a stupid single-character error somewhere
My CPU is partially fried

The problem is that you try to read from an unintialized member of the structure, the very first time it happens is here
if (node->left)
in printtree() function.
Uninitialized values, are kept like that and attempting to read them is undefined behavior, so that's why your program doesn't always behave the same.
You need to initialize both members, in fact it woule be better to have
struct tree *create_node(int content)
{
struct tree *node;
node = malloc(sizeof(*node));
if (node == NULL)
return NULL;
node->content = content;
node->left = NULL;
node->right = NULL;
return node;
}
You should also,
Avoid casting malloc() or any function returning void * because of what's discussed here.
Check that malloc() doesn't return NULL before using the pointer.

For starters the function comp shall be declared like
int comp( const void *, const void * );
Secondly in the function treeify either the data member left of the data member right will have indeterminate value in case when leftsize or rightsize are equal to 0.
The function can be implemented simpler without using auxiliary arrays.
struct tree * treeify( const int *array, size_t size )
{
struct tree *node = NULL;
if ( size )
{
node = malloc( sizeof( struct tree ) );
size_t middle = size / 2;
node->content = array[middle];
node->left = treeify( array, middle );
node->right = treeify( array + middle + 1, size - middle - 1 );
}
return node;
}
The function printtree( is wrong. For example it does not check whether the first parameter is equal to NULL.
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
struct tree
{
int content;
struct tree *left;
struct tree *right;
};
int comp( const void *, const void * );
struct tree * treeify( const int *, size_t );
void printtree( const struct tree *, int level );
int main(void)
{
int array[] = { 5, 6, 7, 2, 3, 4, 9, 1, 8, 0 };
const size_t N = sizeof( array ) / sizeof( *array );
qsort( array, N, sizeof( *array ), comp );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", array[i] );
putchar( '\n' );
struct tree *rootnode = treeify( array, N );
printtree( rootnode, 0 );
return 0;
}
int comp( const void *left, const void *right )
{
int x = *( const int * )left;
int y = *( const int * )right;
return ( y < x ) - ( x < y );
}
struct tree * treeify( const int *array, size_t size )
{
struct tree *node = NULL;
if ( size )
{
node = malloc( sizeof( struct tree ) );
size_t middle = size / 2;
node->content = array[middle];
node->left = treeify( array, middle );
node->right = treeify( array + middle + 1, size - middle - 1 );
}
return node;
}
void printtree( const struct tree *node, int level )
{
if ( node )
{
printf( "%*s", level, "" );
printf( "%d\n", node->content );
if( node->left ) printtree( node->left, level + 1 );
if( node->right ) printtree( node->right, level + 1 );
}
}
Its output is
0 1 2 3 4 5 6 7 8 9
5
2
1
0
4
3
8
7
6
9

Related

Sorting with linked lists using the qsort algorithm

I'm still learning how linked lists works and I'm kinda struggling with the sorting using qsort algorithm and the nodes .
This is what I did so far .
So I'm having a crash somewhere in the code and I don't know if this qsort algorithm works this way with the linked lists or not.
Code Updated
void swapString(char **str1, char **str2)
{
char *temp = *str2;
*str2 = *str1;
*str1 = temp;
}
TCD *partition(TCD *Start, TCD *End, int (*cmp)(const void *, const void*))
{
TCD *partitionIdx = Start;
TCD *i ;
for (i = Start; i != End; i=i->Next)
{
if (cmp(i->Titel, End->Titel) < 0)
{
swapString(&i->Titel, &partitionIdx->Titel);
partitionIdx->Prev = partitionIdx;
partitionIdx = partitionIdx->Next;
}
}
swapString(&partitionIdx->Titel, &End->Titel);
return partitionIdx;
}
void Quicksort(TCD *Start, TCD *End, int (*cmp)(const void *, const void *))
{
if (Start !=NULL && End != Start && End!= Start->Next)
{
TCD *partitionIdx = partition(Start, End, cmp);
Quicksort(Start, partitionIdx->Prev, cmp);
Quicksort(partitionIdx->Next, End, cmp);
}
}
By the way , this is the definition of TCD
typedef struct F
{
char *Titel;
struct F *Next;
struct F *Prev;
}TCD;
There are several problems with your code:
The line partitionIdx->Prev = partitionIdx; does not make sense. It causes a node to point to itself. This cannot be correct. The purpose of a linked list is for a node to point to the next node and the previous node, but never to itself.
Your function partition is crashing because its parameter Start will sometimes point to a place in the linked list beyond the End parameter. This is because you call the function Quicksort without ensuring that its Start parameter does not point to a place beyond the End parameter.
The if condition if ( Start != NULL && End != Start && End != Start->Next ) does not make sense. The sub-expression End != Start->Next tests if the size of the partition is 2. If that is the case, the partition is not processed. However, a partition of size 2 must be sorted, so it must be processed. Only if the size is 1 should it not be processed.
I have changed the code of your algorithm by fixing the issues mentioned above, and it seems to work now. Also, I have added some functions to test the algorithm. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct F
{
char *Titel;
struct F *Next;
struct F *Prev;
} TCD;
void swapString( char **str1, char **str2 )
{
char *temp = *str2;
*str2 = *str1;
*str1 = temp;
}
TCD *partition( TCD *Start, TCD *End, int( *cmp )(const void *, const void*) )
{
TCD *partitionIdx = Start;
TCD *i;
for ( i = Start; i != End; i = i->Next )
{
if ( cmp( i->Titel, End->Titel ) < 0 )
{
swapString( &i->Titel, &partitionIdx->Titel );
//NOTE: I disabled the following line from the original code, as it was doing nonsense. It was causing a node to point to itself.
//partitionIdx->Prev = partitionIdx;
partitionIdx = partitionIdx->Next;
}
}
swapString( &partitionIdx->Titel, &End->Titel );
return partitionIdx;
}
void Quicksort( TCD *Start, TCD *End, int( *cmp )(const void *, const void *) )
{
//NOTE: In the following if condition, I disabled part of the original code, because a partition of two elements must be sorted
if ( Start != NULL && End != Start /*&& End != Start->Next*/ )
{
TCD *partitionIdx = partition( Start, End, cmp );
if ( Start != partitionIdx )
Quicksort( Start, partitionIdx->Prev, cmp );
if ( partitionIdx != End )
Quicksort( partitionIdx->Next, End, cmp );
}
}
// NOTE:
// The following functions are not part of the algorithm, but are only
// used to test the algorithm.
void AddToList( TCD **head, TCD **tail, char *str )
{
TCD *p;
//allocate new node and fill it with the data
p = malloc( sizeof(*p) );
assert( p != NULL );
p->Titel = str;
p->Next = NULL;
p->Prev = *tail;
//attach new node to list by updating head or next pointer
if ( *head == NULL )
*head = p;
else
(*tail)->Next = p;
//update tail pointer too
*tail = p;
}
void PrintList( FILE *stream, TCD *head )
{
TCD *p;
for ( p = head; p != NULL; p = p->Next )
{
fprintf( stream, "%s\n", p->Titel );
}
fprintf( stream, "\n" );
}
void FreeList( TCD *head )
{
TCD *p = head;
while ( p != NULL )
{
TCD *tmp = p;
p = p->Next;
free( tmp );
}
}
int main( void )
{
TCD *head = NULL, *tail = NULL;
//create linked list with a bit of unsorted test data
AddToList( &head, &tail, "string8" );
AddToList( &head, &tail, "string4" );
AddToList( &head, &tail, "string2" );
AddToList( &head, &tail, "string7" );
AddToList( &head, &tail, "string3" );
AddToList( &head, &tail, "string5" );
AddToList( &head, &tail, "string1" );
AddToList( &head, &tail, "string6" );
//print list before sorting
fprintf( stderr, "List before sort:\n" );
PrintList( stderr, head );
//do the actual sorting
Quicksort( head, tail, strcmp );
//print list after sorting
fprintf( stderr, "List after sort:\n" );
PrintList( stderr, head );
//free the linked list
FreeList( head );
return 0;
}

Getting segmentation fault when allocating a linked list and assigning it values in c

I am trying to create a singly linked list and initialize it with the first given n integers.But i am getting segmentation fault whenever i run it.This is my code.
typedef struct floatList{float fval;struct floatList * fnext;}node_f;
node_f* FL_firstInts(int n){
node_f *res=(node_f*)malloc(sizeof(node_f));
res=res->fnext;
for(int i=1;i<=n;i++){
res->fval=i;
res=res->fnext;
}
return res;
}
void FL_show(struct floatList *list, char *label){
int i=0;
while(list->fnext!=NULL){
printf("%d: %f\n",i,f->fval);
list=list->fnext;
i++;
}
}
And in order to test in the main function, i write the following
node_f *ten = FL_firstInts(10);
FL_show(ten,"10 first integers");
But as i run the program, i get segmentation fault,how do i fix it?
In the function FL_firstInts you allocated uninitialized object of the type node_f
node_f *res=(node_f*)malloc(sizeof(node_f));
So the following statement
res=res->fnext;
already invokes undefined behavior.
The function can be defined at least the following way
node_f * FL_firstInts( int n )
{
node_f *head = NULL;
node_f **current = &head;
`
for ( int i = 0; i < n; i++ )
{
*current = malloc( sizeof( node_f ) );
( *current )->fval = i;
( *current )->fnext = NULL;
current = &( *current )->fnext;
}
return head;
}
Th function FL_show has the same bug and moreover the parameter label is not used.
The function can be defined like
void FL_show( const node_f *head, const char *label )
{
if ( label ) puts( label );
for ( int i = 0; list != NULL; list = list->fnext )
{
printf( "%d: %f\n", i, f->fval );
i++;
}
}
node_f *res=(node_f*)malloc(sizeof(node_f));
res=res->fnext;
The reason for your crash is that you're never initialising the res->fnext pointer.
So before accessing it set it to the actual next element in your list.
In general your code is a bit fuzzy.
You're allocating memory for one node_f, but you're actually trying to put n elements into it.
To allocate memory for the n elements just multiply the size of one element by n.
node_f *res= (node_f*) malloc(sizeof(node_f) * n);
Afterwards initialise the fnext pointers.
for(size_t index{0}; index < n - 1; index++)
res[index].fnext = &res[index + 1];
res[n - 1].fnext = nullptr;

How do I Print a Hash Table in C?

I have a program in C that creates a hash table. I want to know what it is, but I am unsure how to print it out or display it. I have pasted the program below. I am rather new to hash tables so any help would be greatly appreciated!
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define TABLE_SIZE 7
#define NUM_INPUTS 7
int hash( char *s )
/* Note, this is a horrible hash function. It's here for
instructional purposes */
{
return strlen( s ) % TABLE_SIZE ;
}
typedef struct entry
{
char *key;
int val;
struct entry *next;
} entry;
entry* table[ TABLE_SIZE ] = { NULL };
void insert( char *s, int v )
/* this insert is NOT checking for duplicates. :/ */
{
int h = hash( s );
entry *t = (entry*) malloc( sizeof( entry ));
t->key = s;
t->val = v;
t->next = table[h];
table[h] = t;
}
void clean_table()
{
entry *p, *q;
int i;
for( i=0; i<TABLE_SIZE; ++i )
{
for( p=table[i]; p!=NULL; p=q )
{
q = p->next;
free( p );
}
} // for each entry
} // clean_table
int main()
{
char* keyList[] = { "Jaga", "Jesse", "Cos", "Kate", "Nash", "Vera",
"Bob" };
int valList[] = { 24, 78, 86, 28, 11, 99, 38 };
int i;
for( i=0; i<NUM_INPUTS; ++i )
insert( keyList[i], valList[i] );
/* what does the table look like here? */
clean_table();
return( 0 );
}
As requested in the comments, a search function as desired would look like this:
int search(const char* key, int* out_val)
{
// Find the hash index into the table.
const int index = hash(key);
// Now do a linear search through the linked list.
for (struct entry* node = table[index]; node; node = node->next)
{
// If we find a node with a matching key:
if (strcmp(node->key, key) == 0)
{
// Output the value and return 1 for success.
*out_val = node->val;
return 1;
}
}
// We didn't find anything. Return 0 for failure.
return 0;
}
Here's an example of a simple Hash Table in C. It doesn't really do any error handling, so this is not at all suitable for production, but it should help to see an example of a working implementation. Here is another post helping someone work through a hash table implementation in C.

Binary Tree storing any data type in c

i'm currently implementing a binary tree in c. After getting the code to work for inserting ints I now want the tree to be able to store any date type i.e. char etc. I'm kind of stumped about how to go about this. I've heard/seen that I can use a void* within my node struct but unsure how you then implement this with regards to inserting elements and comparing void* to see which is bigger or smaller. Any help would be very much appreciated! Thanks
#include <stdio.h>
#include <stdlib.h>
//struct for node of the binary tree
struct node
{
void *value;
struct node *p_left;
struct node *p_right;
};
//recursive function to allow users to input into the tree
void insert(void* key, struct node** leaf )
{
if( *leaf == NULL )
{
*leaf = (struct node*) malloc( sizeof( struct node ) );
(*leaf)->value = key;
(*leaf)->p_left = NULL;
(*leaf)->p_right = NULL;
printf( "\nnew node " );
}
else if( key < (*leaf)->value )
{
printf( "\ngoing left " );
insert( key, &(*leaf)->p_left );
}
else if(key > (*leaf)->value)
{
printf( "\ngoing right " );
insert( key, &(*leaf)->p_right );
}
}
int main(void)
{
struct node *p_root = NULL;
int value ; //i want value to be of any kind
printf( "\nPlease enter a value: " );
scanf( "%d", &value );
insert(value, &p_root);
return 0;
}
You should use void pointers for inserting values and then cast them to their supposed types after.
The thing is, you do not wan't to get "anything" if you know you want to compare which is bigger or smaller later. I suppose you might want to have an additional info in your node which specifies what type is the value actually.
I suppose you want to do this for practice, but in reality would you really want to compare arrays of characters with integers?
#include <stdio.h>
#include <stdlib.h>
struct node {
void *value;
struct node *p_left;
struct node *p_right;
};
typedef int (*Compare)(const void *, const void *);
void insert(void* key, struct node** leaf, Compare cmp){
if( *leaf == NULL ){
*leaf = (struct node*) malloc( sizeof( struct node ) );
(*leaf)->value = key;
(*leaf)->p_left = NULL;
(*leaf)->p_right = NULL;
printf( "\nnew node " );
} else if( cmp(key, (*leaf)->value) < 0) {
printf( "\ngoing left " );
insert( key, &(*leaf)->p_left, cmp);
} else if( cmp(key, (*leaf)->value) > 0){
printf( "\ngoing right " );
insert( key, &(*leaf)->p_right, cmp);
} else {
free(key);
}
}
int CmpInt(const int *a, const int *b){
return *a < *b ? -1 : *a > *b;
}
int *GetInteger(void){
char line[16];
printf("Please enter a value : ");
if(fgets(line, sizeof line, stdin)){
int v, *ret;
char *p;
v = strtol(line, &p, 10);
if(*p == '\n' || *p == '\0'){
int *ret = malloc(sizeof(*ret));
*ret = v;
return ret;
}
}
return NULL;
}
void print_tree(struct node *root, void (*print_func)(const void*) ){
if(root){
print_tree(root->p_left, print_func);
print_func(root->value);
print_tree(root->p_right, print_func);
}
}
void print_int(const void *p){
printf("%d ", *(int*)p);
}
int main(void){
struct node *p_root = NULL;
void *value;//int *value;
while(value = GetInteger()){//upto input EOF or invalid input
insert(value, &p_root, (Compare)CmpInt);
}
print_tree(p_root, print_int);
//release tree omit
return 0;
}

priority queue segmentation fault

I am using a priority queue with a double as the priority. I am guessing this is the cause of the issues. I used these numbers first with no issues.
34.365681
34.481879
34.539832
36.715120
I then used these numbers and had a segmentation fault.
45.411042
40.481879
37.702110
38.951187
struct PRIORITYQUEUE
{
int x_pq;
int y_pq;
double heuristic_pq;
int priority;
int info;
struct PRIORITYQUEUE *next;
}*start, *q, *temp, *new;
typedef struct PRIORITYQUEUE *N;
void insert(int x, int y, double heuristic)
{
int item;
double itprio;
//new = ( N* ) malloc( sizeof( N ) );
new = malloc( sizeof( N ) );
itprio = heuristic;
new->x_pq = x;
new->y_pq = y;
new->heuristic_pq = itprio;
if ( start == NULL || itprio < start->heuristic_pq )
{
new->next = start;
start = new;
}
else
{
q = start;
while ( q->next != NULL && q->next->heuristic_pq <= itprio )
q = q->next;
new->next = q->next;
q->next = new;
}
}
void del()
{
if ( start == NULL )
{
printf( "\nQUEUE UNDERFLOW\n" );
}
else
{
new = start;
printf( "\nDELETED ITEM IS %d\n", new->info );
start = start->next;
free( start );
}
}
void display()
{
temp = start;
if ( start == NULL )
printf( "QUEUE IS EMPTY\n" );
else
{
printf( "QUEUE IS:\n" );
while ( temp != NULL )
{
printf( "\t x is %d y is %d[heuristic=%lf] \n", temp->x_pq, temp->y_pq, temp->heuristic_pq );
temp = temp->next;
}
}
}
Your problem lies with this code:
typedef struct PRIORITYQUEUE *N;
:
new = malloc( sizeof( N ) );
The type N is a pointer to that structure of yours, not the structure itself. That means that sizeof(N) is likely to be much smaller than the structure, meaning that you're not allocating enough memory.
You could see this by inserting this immediately after the allocation:
printf ("%zd %zd\n", sizeof (N), sizeof (struct PRIORITYQUEUE));
and you'll probably see a series of lines of the form 4 32 or 8 32, showing that, while you've allocated four or eight bytes, you need 32.
That's what's causing your crashes. Now, as to how to fix it, it's simply making sure you allocate enough space for the structure and this can be done with either of:
new = malloc (sizeof (struct PRIORITYQUEUE));
new = malloc (sizeof (*N));
But the one I prefer is:
new = malloc (sizeof (*new));
The reason I prefer it is that it ties the allocation quantity to the variable you using. While the earlier two will handle any changes to the structure size, this one will even survive declaring new as a totally different structure without having to change information in multiple places.
By that I mean, if you change the type of new thus:
struct FASTER_PRIO_Q *new;
then you would be required to change the allocation statements as well for the first two cases. Not so for the third.

Resources