Segfault with a quicksort implementation in C - c

I am debugging my code for a quick sort algorithm in C. It compiles but fails with a "Segmentation fault" when running it.
Can anybody help me to debug it and give me the working version of my code? I know there are existing and working ones on the internet. But what I really want is to find the bug of my own code.
void myQuickSort(int list[],int head, int tail)
{
int m = head;
int n = tail;
int key = list[m];
++head;
while(head < tail)
{
while(list[head] < key)
{
++head;
}
while(list[tail] >= key)
{
--tail;
}
//swamp two elements, to divide the array to two groups
int temp = list[head];
list[head] = list[tail];
list[tail] = temp;
}
//get the pivot element in dividing position
int temp = list[m];
list[m] = list[head];
list[head] = temp;
myQuickSort(list, m, head-1);
myQuickSort(list, head+1, n);
}

Your function will never exit.
It will keep calling itself until the call stack is full and cause a stack overflow exception.
The compiler should generate a warning for this:
warning C4717: 'myQuickSort' : recursive on all control paths, function will cause runtime stack overflow
You need an exit condition, something along the lines of:
void myQuickSort(int list[],int head, int tail)
{
//exit condition, or else the function will always call itself
if ( head >= tail )
return;
/**
...
*/
myQuickSort(list, m, head-1);
myQuickSort(list, head+1, n);
}
Also, make sure you call the function like:
int num[5] = {1,4,2,3,5};
myQuickSort(num,0,4);
the final parameter must be 1 less than the length of the array since C++ arrays are 0-based.
You also need one extra check in your while loops:
while( head < tail && list[head] < key ) // see if head reached the end
{
++head;
}
while( head < tail && list[tail] >= key )
{
--tail;
}
or else you might pass the end of the array.

Just looking at it quickly, I see a number of places where this could segfault. For example, here:
while(list[head] < key)
{
++head;
}
Imagine a list where key was, by chance, the largest element in the list. This loop will then run until head is past the end of the array, at which point a segfault can occur at any time. Likewise, the following loop can cause tail to move off the beginning of the array.

In addition to the guaranteed stack overflow diagnosed by Luchian, you need to check that you don't run off the array in the inner loop:
while(head <= tail && list[head] < key)
while(head <= tail && list[tail] >= key)

Related

Increment integer pointer in a loop in C

My original code to display nodes in a queue in order from lowest to greatest:
void display (queue *q) {
node *ptr = q->front;
int i = 0;
int size = q->size;
while (i <= size) {
while (ptr->id != i) {
ptr = ptr->next;
}
if (i == 0) {
printf("%d ", ptr->id);
printf("%d\n", ptr->running);
}
else {
printf("%d ", ptr->id);
}
i++;
ptr = q->front;
}
}
Had kept producing Segmentation Fault (Core Dumped) errors. I have malloc the two variables being compared and this error has been fixed.
void display (queue *q) {
node *ptr = malloc(10);
ptr = q->front;
int *i = NULL;
i = malloc(sizeof(int));
*i = 0;
int size = q->size;
while(*i <= size){
while (ptr->id != *i) {
ptr = ptr->next;
}
if (*i == 0) {
printf("%d %d\n", ptr->id, ptr->running);
}
else {
printf("%d %d %d %d\n", ptr->id, ptr->running, ptr->ready, ptr->blocked);
}
i = i + 1 * (sizeof(char));
ptr = q->front;
}
}
However now this doesn't produce the output that I want. I want to increment the i pointer so that it can be the same as my original code.
This has been immensely frustrating, any help would be greatly appreciated!
If I read your first code listing correctly, there's at least one important thing here you need to think about. You seem to have a linked list here, and you're iterating over that list using ptr = ptr->next. This means you need to know when to stop. One common way of setting up a linked list is that the last item in the list has a next value of NULL. Then process the nodes one at a time, and once you are done with one node, you you check whether the next value is NULL: if it isn't you can move on that that next node, if it is NULL you stop.
Here you're not doing checks like this, so you need another way to ensure that you know when to stop. What you seem to be doing is taking the value of q->size and using that to inform you how many items there are in the linked list. So the first thing to think about is how confident you are that that value is correct. For example, if the code building the list puts only two items into the list, bet sets size to three, you'll end up falling off the end of the list, and a segmentation fault is not unlikely.
But there's something even more important than that. Even if you're getting the correct number of items in the list from q->size, you're comparing your loop variable i to size like this:
int i = 0;
while (i <= size) {
⋮
}
This is going to loop with i having the values [ 0, 1, … size ], which is actually size + 1 times. If you want to loop exactly size times, you want a test like i < size rather than i <= size. This is a common mistake, often called an off-by-one error.
Unfortunately, your second listing complicates things, rather than making them better. Go back to your first one and see if you can fix the things I've mentioned here.

Can someone help me find the segfault here?

EDIT: So, it turns out that 'index' was not being returned to 0. Well then. That fixed one segfault. But still getting a different segfault. Working on it.
node* new_node(void){
node* ptr = malloc(sizeof(node));
for (int i = 0; i<27; i++) {
ptr->next[i] = NULL;
}
return ptr;
}
bool load(const char* dictionary)
{
FILE* dict = fopen(dictionary, "r");
node* ptr = new_node;
char word[LENGTH+1];
int index = 0;
for (int c = fgetc(dict); c!=EOF; c = fgetc(dict)){
if(c!='\n'){
word[index]=c;
index++;
}
else {
for(int x=0; x<=index; x++){
int ch = (word[x] == '\'') ? 26 : tolower(word[x])-'a';
if (ptr->next[ch] == NULL){
ptr->next[ch] = new_node;
}
ptr = ptr->next[ch];
}
ptr->end=true;
}
}
return true;
}
I'm trying to implement a trie data structure for a dictionary but my program seems to segfault somewhere in this function. I can't seem to pin it down even with the help of GDB, so can someone give me a hand?
Node is defined as such:
typedef struct node{
bool end;
struct node* next[27];
} node;
Dictionary file:
a
aaa
aaas
aachen
aalborg
aalesund
aardvark
aardvark's
aardvarks
aardwolf
(...)
You have many issues in your code:
When you allocate memory with malloc, it is uninitialised. initialise it directly after allocating it, so that NULL pointers really are null. (calloc, a cousin of ´malloc´, initialises all memory to zero.)
When you loop over the word, you should nor include index:
for (int x = 0; x < index; x++) ...
When you have found the end of a word, you must reset the index to 0. Otherwise, you will append to the old word and overflow the buffer. (You should probably also enforce the upper bound of ´index´.)
Likewise, when you insert a word into the trie, you must reset your pointer for trie traversal to the trie's root. You need two pointers here: A root node pointer and an auxiliary pointer for traversing the trie.
As is, your trie is local to your function. Return the root node, so that other functions can use the trie, or NULL on failure.
Fix these, and you will have a non-crashing function. (It still leaks memory and may not construct the trie properly.)
node *load(const char *dictionary)
{
FILE *dict = fopen(dictionary, "r");
node *head = calloc(1, sizeof(node));
char word[LENGTH + 1];
int index = 0;
for (int c = fgetc(dict); c != EOF; c = fgetc(dict)) {
if (c != '\n') {
word[index] = c;
index++;
} else {
node *ptr = head;
for (int x = 0; x < index; x++) {
int ch = (word[x] == '\'') ? 26 : tolower(word[x]) - 'a';
if (ptr->next[ch] == NULL) {
ptr->next[ch] = calloc(1, sizeof(node));
}
ptr = ptr->next[ch];
}
ptr->end = true;
index = 0;
}
}
return head;
}
The line:
node* ptr = new_node;
and
ptr->next[ch] = new_node;
are not calling the function, but assigning the address of the function to ptr. Call the function instead.
This problem could have been prevented if compiler warnings: -Wall and -Wextra were enabled.
There is no bounds checking done on the array word. Use the value LENGTH to check if the index is in bounds before using it.
It isn't clear what the if statement inside the for loop is doing. It appears that every time a newline is found the whole array word is added to the tree, but the index isn't reset so the same array is added multiple times. At some point index will point out of bounds causing undefined behavior. You should reset index after you use the array word.
You forgot to reset index to 0 at the beginning of the loop.
You should also use calloc(1, sizeof(node)) instead of malloc(sizeof(node)) to avoid leaving memory uninitialized. I suggest you use valgrind to help you track problems of this kind in your code.
You should filter punctuation\unsupported characters a bit more. Any character outside of [a-z|A-Z|\n|\\] will crash your program because of
int ch = (word[x] == '\'') ? 26 : tolower(word[x])-'a';
if (ptr->next[ch] == NULL){
Given that you open a file, there might be a space somewhere or some unexpected character. You need something like
if(c!='\n'){
int num = (c == '\'') ? 26 : tolower(c)-'a');
if(num >=0 && num < 27)
{
word[index]=c;
index++;
}
}

C: Help understanding pointers

I have been building this hash table function that is given an array it gets a word from and a pointer to an array that it fills with my linked list struct. It compiles correctly but I get a segmentation fault at - *hashTable[hashVal] = *newNode; .
void hashTableCreate(char *array, list *hashTable[]) {
while(arrayPos < getArrayLength(array)) {
char *temp = getWord(array);
int hashVal = hashingFunc(temp);
if((*hashTable[hashVal]).word == temp ) {
(*hashTable[hashVal]).count = (*hashTable[hashVal]).count+1;
}
else {
list *newNode = malloc(sizeof(list));
strcpy(newNode->word,temp);
newNode->count = 1;
*hashTable[hashVal] = *newNode;
}
}
}
It's called like this:
void timeStructures(char *newArray) {
list *hashTable[3000];
hashTableCreate(newArray, hashTable);
}
I know this is to do with the way I am using my pointers but I can't figure it out. Any help would be appreciated.
There are several problems on this code:
You seem you are using extra asterisks when assigning newNode to hashTable.
You can use ++ operator to increment count, and use -> to access a member of a pointer to struct.
getWord is unknown to me, but seems impossible it can return a pointer to a string contained inside an element of hashTable, which means the next if will always be false (newNode's word is a copied string, not a pointer to array's word), as it compares memory addresses instead of strings.
You never free temp neither hashTable elements, which seems another misconception of what you are doing here.
As noted by #kaylum , you should initialize hashTable so you avoid comparing against unassigned array elements, neither modifying count on them.
hashTable has to be passed as a pointer to hashTableCreate, or this will work on a copied version of it:
Try this:
void hashTableCreate(char *array, list *(*hashTable[])) {
while(arrayPos < getArrayLength(array)) {
char *temp = getWord(array);
int hashVal = hashingFunc(temp);
if((*hashTable)[hashVal] != NULL &&
strcmp((*hashTable)[hashVal]->word, temp) == 0 ) {
(*hashTable)[hashVal]->count++;
}
else {
list *newNode = malloc(sizeof(list));
strcpy(newNode->word,temp);
newNode->count = 1;
(*hashTable)[hashVal] = newNode;
}
free(temp);
}
}
void timeStructures(char *newArray) {
list *hashTable[3000];
int i;
// Initialize hashTable pointers to NULL
for(i = 0; i < 3000; i++) {
hashTable[i] = NULL;
}
hashTableCreate(newArray, &hashTable);
// Free hashTable elements, malloc'ed at hashTableCreate
for(i = 0; i < 3000; i++) {
if(hashTable[i] != NULL) {
free(hashTable[i]);
}
}
}
Note 1: you never check if hashVal is higher than 3000, which might be fine if you know what you are doing, aka, you know hashingFunc will never return 3000 or higher. If you do not, you'll need to care about growing hashTable appropriately.
Note 2: executing getArrayLength on each loop might be a performance problem for large lists. You probably prefer to create a variable to contain its value and execute it only once.
Note 3: It might be some easier if you declare hashTable as a plain list of elements, not a list of pointers to elements, like list hashTable[3000];, but I don't know exactly what you're looking for. Also, it will always waste 3000 list elements of memory, so might be a performance problem.

Pointer becomes null

I'm passing a file pointer to a function(A) which then opens the file, reads a line in a while loop (for each line in the file) and calls another function(B) using theses values. The issue is after running through function B once, the file pointer becomes NULL and I'm not sure why.
void readMatrixData(matrix *matrix, FILE *fileInput)
{
char buffer[30];
while(fgets(buffer, 30, fileInput) != NULL) {
char *splitString = strtok(buffer, ",");
int row = atoi(splitString);
splitString = strtok(NULL, ",");
int column = atoi(splitString);
splitString = strtok(NULL, ",");
int value = atoi(splitString);
insertNewNode(&matrix->rowArray[row], &matrix->columnArray[column], value, row, column);
}
}
I check if fopen returns NULL before calling function A, and it's not. I've also set a breakpoint on the while loop and the first time it hits, fileInput has some memory allocated. However, on the second loop fileInput becomes NULL and I'm not sure why.
EDIT:
Here's the insertNewNode function:
void insertNewNode(node **rowHead, node **columnHead, int value, int row, int column) {
//Get to the correct position in the column linked list
if (*columnHead == NULL) {
*columnHead = malloc(sizeof(node));
} else {
while((*columnHead)->nextColumn != NULL && (*columnHead)->nextColumn->row < row)
*columnHead = (*columnHead)->nextColumn;
}
//Get to the correct position in the row linked list.
if (*rowHead == NULL) {
*rowHead = malloc(sizeof(node));
} else {
while((*rowHead)->nextRow != NULL && ((*rowHead)->nextRow->column < column))
*rowHead = (*rowHead)->nextRow;
}
node *newNode = malloc(sizeof(node));
newNode->column = column;
newNode->row = row;
newNode->value = value;
(*columnHead)->nextColumn = newNode;
(*rowHead)->nextRow = newNode;
}
The structs involved are:
typedef struct matrix {
node **rowArray;
node **columnArray;
Size matrixDimensions;
} matrix;
typedef struct node {
int value;
int row;
int column;
struct node *nextColumn;
struct node *nextRow;
} node;
and I initialise the matrix arrays with:
node *columns[m->matrixDimensions.columns];
node *rows[m->matrixDimensions.rows];
for (int i=0; i< m->matrixDimensions.columns; i++)
{
columns[i] = NULL;
}
for (int i=0; i < m->matrixDimensions.rows; i++)
{
rows[i] = NULL;
}
m->columnArray = columns;
m->rowArray = rows;
Probably the function insertNewNode overwrites memory
Prefer strtol over atoi.
As #DavideBerra suggested, comment out the call to insertNewNode and step through the code to confirm you can make multiple iterations of your while loop.
I don't understand how you are initialising your matrix arrays using m->matrixDimensions.columns and m->matrixDimensions.rows. Are you using C99 VLAs?
Crank up the warning levels of your compiler and ensure zero-warning compilation.
You do not initialize the nextRow and nextColumn fields of your newly allocated node. Doing so should prevent you from at least some trouble. It is strange that you do not get a Segfault.
You are also mixing array and linked list, what could happen if you get "overflowing" values from your file ? I feel like the segfault is not far away from here. Be very careful, your code shows weird concept mixing !
As others had suggested you, comment your insertNewNode call and see if your loop is well performed. If it is, run your program step by step using a debugger. Hope this helps, good luck !
check the value of row and column before accessing matrix->rowArray and matrix->columnArray whether these values are less than the array size.
My guess is that the values row,column may be outside your matrix and thus overwriting memory. Add a check of the values you receive and make sure your matrix is large enough. Remember arrays are zero indexed in C.

Stop condition for printing linked structs?

I have the following struct:
struct cell {
int nmbr;
struct cell *p;
};
I have created a chain of linked structs from this type. Every struct is connected to its predecessor through *p. If I decide to print all nmbrs with a recursive algorithm as shown below, how do I define the stop condition?
void write(struct cell* l) {
/* The following if statement doesn't solve my problem,
but hopefully you see what I'm trying to do */
if (&l != 0x000000) {
printf("%d \t", l->nmbr);
write(l->p);
}
}
You want
if (l != 0)
or
if (l != NULL)
Of course, you also need to make sure that the tail of your linked list has p assigned NULL as well; otherwise it will be uninitialized and probably something not NULL but invalid anyway.
You should check against 'l' not being NULL rather than '&l' assuming that the linked list in NULL terminated.
Assuming the linked list is not cyclic, you just stop when you reach a null pointer.
Change
if (&l != 0x000000)
to
if (l != NULL)
As others have said, you should check l (el), not &l, against 0 or NULL. So, your function should look something like:
void write(CELL* l) {
if (l != 0x000000) {
printf("%d \t", l->nmbr);
write(l->p);
}
}
That said, it is easy to accomplish the same thing using a while, thus avoiding the overhead of recursion:
list_pos = list_head;
while (list_pos != NULL) {
printf("%d \t", list_pos->nmbr);
list_pos = list_pos -> p;
}
the print number up here, for the current node.
if(l->p!=NULL)
write(l->p);

Resources