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.
Related
I use this structure for my tree:
typedef struct product{
char name[50];
char id[5];
double price;
int amount;
struct product *left_p, *right_p;
}product_t;
So, I must convert the tree into an array.
I wrote this for the tree dimension:
int tree_dim(product_t *node_p){
int i = 1 ;
if (node_p == NULL)
i = 0;
else{
i += tree_dim(node_p->left_p);
i += tree_dim(node_p->right_p);
}
return i;
}
My tree is populated by reading the records from a txt file. The records are 21 and the value returned by tree_dim is correct. The value is stored inarr_dim.
Then I create aproduct_t *products_a; wich will be the "array" and allocate it in memory by using products_a = malloc (arr_dim*sizeof (product_t));
Now, this is the function to fill the array with the tree nodes:
void fill_array(int *index, product_t *node_p, product_t *products_a){
if (node_p != NULL){
fill_array(index, node_p->left_p, products_a);
products_a[*index++] = *node_p;
fill_array(index, node_p->right_p, products_a);
}
}
But it gives me segmentation fault error so I also tried this 2nd solution:
int fill_array(product_t *node_p, product_t *products_a){
int i = 1 ;
if (node_p == NULL){
i=0;
}
else
{
i += fill_array(node_p->left_p, products_a);
products_a[i-1] = *node_p;
i += fill_array(node_p->right_p, products_a);
}
return i;
}
Which doesn't give segmentation fault but when I print the array there are empty positions.
I need some tips on where I'm wrong. Maybe a problem with the index and the recursive calls but I can't figure it out.
Look at the precedence of these two operators
*index++
++ Incrementation has higher precedence than * dereference right?
So if you first move in memory by sizeof(int) then you arent no more in your allocated memory and dereferencing would cause UB.
Its always better to use brackets () if you arent sure about precedence.
(*index)++ // This is right
Filip has already pointed out the problem with your first function.
The problem with your second function is that it works only when filling from the left branch. After you have done that and copied the current product, there are some elements in the array, but copying from the right branch will start at index 0 again, so it will overwrite existing data and leave data at the end uninitialised.
You could fix this by passing the current index i to your function, but I find the i = func(..., i); syntax a bit redundant.
In C, you can pass in a subarray of array starting at element i with &array[i] or just array + i. (Remember that an array in a function call "decays" into a pointer to the first element, &array[0].)
So this will work:
int fill_array(product_t *node_p, product_t *products_a)
{
int i = 0;
if (node_p == NULL) return 0;
i += fill_array(node_p->left_p, products_a);
products_a[i++] = *node_p;
i += fill_array(node_p->right_p, &products_a[i]);
return i;
}
Disclaimer, this is help with a school assignment. That being said, my issue only occurs about 50% of the time. Meaning if I compile and run my code without edits sometimes it will make it through to the end and other times it will not. Through the use of multiple print statements I know exactly where the issue is occurring when it does. The issue occurs in my second call to hugeDestroyer(right after the print 354913546879519843519843548943513179 portion) and more exactly at the free(p->digits) portion.
I have tried the advice found here (free a pointer to dynamic array in c) and setting the pointers to NULL after freeing them with no luck.
Through some digging and soul searching I have learned a little more about how free works from (How do malloc() and free() work?) and I wonder if my issue stems from what user Juergen mentions in his answer and that I am "overwriting" admin data in the free list.
To be clear, my question is two-fold.
Is free(p->digits) syntactically correct and if so why might I have trouble half the time when running the code?
Secondly, how can I guard against this kind of behavior in my functions?
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct HugeInteger
{
// a dynamically allocated array to hold the digits of a huge integer
int *digits;
// the number of digits in the huge integer (approx. equal to array length)
int length;
} HugeInteger;
// Functional Prototypes
int str2int(char str) //converts single digit numbers contained in strings to their int value
{
return str - 48;
}
HugeInteger *parseInt(unsigned int n)
{
int i = 0, j = 0;
int *a = (int *)calloc(10, sizeof(int));
HugeInteger *p = (HugeInteger *)calloc(1, sizeof(HugeInteger));
if(n == 0)
{
p->digits = (int *)calloc(1, sizeof(int));
p->length = 1;
return p;
}
while(n != 0)
{
a[i] = n % 10;
n = n / 10;
i++;
}
p->length = i;
p->digits = (int *)calloc(p->length, sizeof(int));
for(i = 0; i <= p->length; i++, j++)
p->digits[j] = a[i];
return p;
}
HugeInteger *parseString(char *str) //notice datatype is char (as in char array), so a simple for loop should convert to huge int array
{
int i = 0, j = 0;
HugeInteger *p = (HugeInteger *)calloc(1, sizeof(HugeInteger));
if(str == NULL)
{
free(p);
p = NULL;
return p;
}
else
{
for(i=0; str[i] != '\0'; i++)
;
p->length = i;
p->digits = (int *)calloc(p->length, sizeof(int));
for(; i >= 0; i--)
p->digits[j++] = str2int(str[i - 1]);
}
return p;
} //end of HugeInteger *parseString(char *str)
HugeInteger *hugeDestroyer(HugeInteger *p)
{
//printf("No problem as we enter the function\n");
if(p == NULL)
return p;
//printf("No problem after checking for p = NULL\n");
if(p->digits == NULL)
{
free(p);
p = NULL;
return p;
}
//printf("No Problem after checking if p->digits = NULL\n");
//else
//{
free(p->digits);
printf("We made it through free(p->digits)\n");
p->digits = NULL;
printf("We made it through p->digits = NULL\n");
free(p);
printf("We made it through free(p)\n");
p = NULL;
printf("We made it through p = NULL\n");
return p;
//}
//return NULL;
}//end of HugeInteger *hugeDestroyer(HugeInteger *p)
// print a HugeInteger (followed by a newline character)
void hugePrint(HugeInteger *p)
{
int i;
if (p == NULL || p->digits == NULL)
{
printf("(null pointer)\n");
return;
}
for (i = p->length - 1; i >= 0; i--)
printf("%d", p->digits[i]);
printf("\n");
}
int main(void)
{
HugeInteger *p;
hugePrint(p = parseString("12345"));
hugeDestroyer(p);
hugePrint(p = parseString("354913546879519843519843548943513179"));
hugeDestroyer(p);
hugePrint(p = parseString(NULL));
hugeDestroyer(p);
hugePrint(p = parseInt(246810));
hugeDestroyer(p);
hugePrint(p = parseInt(0));
hugeDestroyer(p);
hugePrint(p = parseInt(INT_MAX));
hugeDestroyer(p);
//hugePrint(p = parseInt(UINT_MAX));
//hugeDestroyer(p);
return 0;
}
First of all, really outstanding question. You did a lot of research on topic and generally speaking, solved this issue by yourself, I'm here mainly to confirm your findings.
Is free(p->digits) syntactically correct and if so why might I have trouble half the time when running the code?
Syntax is correct. #Shihab suggested in comments not to release p->digits and release p only, but such suggestion is wrong, it leads to memory leakages. There is a simple rule: for each calloc you must eventually call free, so your current approach in freeing p->digits and then p is totally fine.
However, program fails on a valid line. How is it possible? Quick answer: free can't do its work due to corruption of meta information responsible for tracking allocated/free blocks lists. At some point program corrupted meta information, but this was revealed only on attempt to use it.
As you already discovered, in most implementations memory routines such as calloc results into allocation of buffer with prepended meta-info. You receives pointer to buffer itself, but small piece of information right before this pointer is crucial for further buffer managing (e.g. freeing). Writing 11 integers into buffer intended for 10, you're likely to corrupt meta-info of block following the buffer. Whether corruption actually happens and what would be its consequences, is heavily dependent on both implementation specifics and current memory alignment (what block follows the buffer, what exactly meta-data is corrupted). It doesn't surprise me, that you see one crash per two executions, neither surprises me observing 100% crash reproduction on my system.
Secondly, how can I guard against this kind of behavior in my functions?
Let's start with fixing overflows. There are couple of them:
parseString: loop for(; i >= 0; i--) is executed length+1 times, so p->digits is overflown
parseInt: loop for (i = 0; i <= p->length; i++, j++) is executed length+1 times, so p->digits is overflown
Direct access to memory managing in C++ is error prone and troublesome to debug. Memory leakages and buffers overflows are the worst nightmare in programmers life, it's usually better to simplify/reduce direct usage of dynamic memory, unless you are studying to cope with it, of course. If you need to stick with a lot of direct memory managing, take a look at valgrind, it's intended to detect all such things.
By the way, there is also a memory leakage in your program: each call to parseInt allocates buffer for a, but never frees it.
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.
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.
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)