I've created a linked list were each node contains a structure as element and a pointer to the next node as follows
list.h
typedef struct node {
group data;
struct node *next;
} node;
typedef struct group {
unsigned int elements_count;
unsigned int closed;
unsigned int members[4];
} group;
list.c
node *add(node *head, group toadd) {
node *n_node = (node*) malloc(sizeof(node));
if(n_node != NULL) {
n_node->next = head;
group *n_group = &n_node->data;
/* Copy the values of the group into the created node */
n_group->elements_count = toadd.elements_count;
n_group->closed = toadd.closed;
for(int i = 0; i < 4; i++)
n_group->members[i] = toadd.members[i];
}
else {
throw_error("malloc returned a NULL pointer");
}
return n_node;
}
The problem arise when I try to read the first element of the array (node->data.members[0]).
Valgrind says that the problem is an invalid read of size 4 where the address is not stack'd, malloc'd or (recentrly) free'd.
Why am I getting a segmentation fault even if I have used malloc to allocate each node?
EDIT:
main.c
node *group_list = NULL;
/* Other code here.. */
group *cur_group = is_present(group_list, msg_gest.mtype);
if(cur_group == NULL) {
// The group isn't still present in the group list, then add it
group new_group = {
.elements_count = 0,
.closed = 0,
.members = {-1, -1 , -1, -1}
};
new_group.members[new_group.elements_count++] = msg_gest.mtype;
new_group.members[new_group.elements_count++] = msg_gest.to_add;
new_group.closed = msg_gest.to_close;
group_list = add(group_list, new_group);
} else {
cur_group->members[cur_group->elements_count++] = msg_gest.to_add;
cur_group->closed = msg_gest.to_close;
}
is_present
group* is_present(node *head, int matr) {
group *c_group;
node *c_node = head;
while(c_node != NULL) {
c_group = &c_node->data;
if(*(c_group->members) == matr) // !!Segmentation fault is caused by this read
return c_group;
printf("\n%d", *(c_group->members));
c_node = c_node->next;
}
return NULL;
}
I think that the problem was caused by an heap overflow, to solve it I've modified the node struct as follows
typedef struct node {
group* data;
struct node *next;
} node;
and I allocated the group within the add function like this
n_node->data = (group*) malloc(sizeof(group));
Try replacing the line
if(*(c_group->members) == matr)
With
if(c_group->members[0] == matr)
Related
Hi I'm new to C and pointers and are having issues trying to implement the below doubly linked list structure. Memory leaks happened in listInsertEnd I believe? I am very confused as to why one work (at least no mem leak in output) and the other one doesn't. I have pasted only parts of the program, any help or explanation is much appreciated.
#include <stdio.h>
#include <stdlib.h>
typedef struct node *Node;
struct node {
int value;
Node next;
Node prev;
};
typedef struct list *List;
struct list {
Node first;
Node last;
int count;
};
Node newNode(int value) {
Node n = malloc(sizeof(*n));
if (n == NULL) fprintf(stderr, "couldn't create new node\n");
n->value = value;
n->next = NULL;
n->prev = NULL;
return n;
}
void listInsertEnd(List newList, int value) {
Node n = newNode(value);
if (newList== NULL) { //no item in list
//why is this giving me memory leaks
newList->first = newList->last = n;
//whereas this doesn't?
newList->first = newList->last = newNode(value);
} else { //add to end
n->prev = newList->last;
newList->last->next = n;
newList->last = n;
}
nList->count++;
}
First of all, talking about memory leaks: there is no direct memory leak in your code. If the leak happens somewhere, it's outside of these functions. It's most probably because you create one or more nodes and then forget to free() them, but this has nothing to do with the two functions you show.
I see that you are using typedef to declare simple pointer types, take a look at this question and answer to understand why that's bad practice and should be avoided: Is it a good idea to typedef pointers?. Also, this particular piece of Linux kernel documentation which explains the issue in more detail.
Secondly, the real problem in the code you show is that you are using pointers after you tested that they are invalid (NULL).
Here:
Node newNode(int value) {
Node n = malloc(sizeof(*n));
if (n == NULL) fprintf(stderr, "couldn't create new node\n");
n->value = value;
// ^^^^^^^^ BAD!
And also here:
if (newList== NULL) {
newList->first = newList->last = n;
// ^^^^^^^^^^^^^^ BAD!
If something is NULL, you cannot dereference it. Change your functions to safely abort after they detect an invalid pointer.
This can be done in multiple ways. Here's an example of correct code:
Node newNode(int value) {
Node n = malloc(sizeof(*n));
if (n == NULL) {
fprintf(stderr, "couldn't create new node\n");
return NULL;
}
n->value = value;
n->next = NULL;
n->prev = NULL;
return n;
}
void listInsertEnd(List newList, int value) {
Node n;
if (newList == NULL) {
return;
// You probably want to return some error value here.
// In that case change the function signature accordingly.
}
n = newNode(value);
if (newList->count == 0) {
newList->first = newList->last = n;
} else { //add to end
n->prev = newList->last;
newList->last->next = n;
newList->last = n;
}
newList->count++;
}
NOTE: the check newList->count == 0 assumes that you correctly increment/decrement the count when adding/removing elements.
This typedef declaration
typedef struct node *Node;
is confusing and presents a bad style. Consider for example this statement
Node n = malloc(sizeof(*n));
somebody can think that here is a typo and should be written
Node *n = malloc(sizeof(*n));
The function
void listInsertEnd(List newList, int value) {
Node n = newNode(value);
if (newList== NULL) { //no item in list
//why is this giving me memory leaks
newList->first = newList->last = n;
//whereas this doesn't?
newList->first = newList->last = newNode(value);
} else { //add to end
n->prev = newList->last;
newList->last->next = n;
newList->last = n;
}
nList->count++;
}
has undefined behavior. If newList is equal to NULL then you are trying to use memory pointed to by a null pointer.
if (newList== NULL) { //no item in list
//why is this giving me memory leaks
newList->first = newList->last = n;
//whereas this doesn't?
newList->first = newList->last = newNode(value);
And initially data members newList->first and newList->last can be equal to NULL. That also can be reason of undefined behavior because the function does not take this into account.
Before changing the function listInsertEnd you should define the function newNode the following way
Node newNode(int value)
{
Node n = malloc(sizeof(*n));
if ( n != NULL )
{
n->value = value;
n->next = NULL;
n->prev = NULL;
}
return n;
}
The function shall not issue any message. It is the caller of the function that decides whether to issue a message if it is required.
In this case the function listInsertEnd can be written the following way
int listInsertEnd(List newList, int value)
{
Node n = newNode(value);
int success = n != NULL;
if ( success )
{
n->prev = newList->last;
if ( newList->first == NULL )
{
newList->first = newList->last = n;
}
else
{
newList->last = newList->last->next = n;
}
++newList->count;
}
return success;
}
Within the main you should create the list the following way
int main( void )
{
struct list list1 = { .first = NULL, .last = NULL, .count = 0 };
// or
// struct list list1 = { NULL, NULL, 0 };
and call the function like
listInsertEnd) &list1, some_integer_value );
I'm having these two structures:
typedef struct node {
int info;
struct node *left, *right;
}NODE;
typedef struct bst {
NODE *root;
}BST;
And these functions:
NODE *newNode(int info) {
NODE *tmp = (NODE *)malloc(sizeof(NODE));
tmp->left = tmp->right = NULL;
tmp->info = info;
return tmp;
}
void addTree(BST **bst, int info) {
if (*bst == NULL) {
(*bst)->root = newNode(info); // <- Breaks the program
return;
}
else while ((*bst)->root != NULL) {
if (info < (*bst)->root->info)
(*bst)->root = (*bst)->root->left;
if (info >(*bst)->root->info)
(*bst)->root = (*bst)->root->right;
}
(*bst)->root->info = info; // <- Breaks the program
}
I can't figure out what have I've done wrong.
I'm calling the function like this in the main function:
addTree(&binST, tmp);
I've used the debugger and it gives me not a single error or warning.
Any help would be appreciated.
if (*bst == NULL) {
(*bst)->root = newNode(info); // <- Breaks the program
Excatly problem lies here , as *bst is NULL then in next line you dereference it (as you try to access struct member) which causes undefined behaviour and crash in your case .
You need to allocate memory to *bst before access members of the structure. Like this -
if (*bst == NULL) {
*bst=malloc(sizeof(BST)); //allocate memory first and then access struct members
(*bst)->root = newNode(info);
Note - Remember to free allocated memory.
I'm pretty new to C world and I don't know how is the correct way to delete this data structure avoiding memory leaks and segmentation faults.
The data structure is this:
typedef struct Node {
int id;
struct Node *parent; /* node's parent */
struct Node *suffix_node;
int first_char_index;
int last_char_index;
bool is_leaf;
struct Node **children; /* node's children */
int children_size; /* size of children structure */
int children_count; /* # of children */
int depth;
}Node;
typedef struct SuffixTree {
Node *root;
int nodes_count;
char *string;
}SuffixTree;
What I would do is, from a pointer to SuffixTree structure, freeing entirely tree.
I have tried to do this:
void deleteSubTree(Node *nd)
{
if (nd->is_leaf)
{
free(nd->children);
free(nd);
return;
}
int i = 0;
for(;i < nd->children_count; ++i)
{
deleteSubTree(nd->children[i]);
}
free(nd->children);
free(nd);
return;
}
void deleteSuffixTree(SuffixTree *st)
{
deleteSubTree(st->root);
free(st);
}
But it is not correct.
EDIT:
This is main:
int main()
{ char *str = "BOOK\0";
SuffixTree *st = createSuffixTree(str);
deleteSuffixTree(st);
return 0;
}
And this is how I allocate tree and nodes:
Node* createNode(){
Node *stn = (Node*)malloc(sizeof(Node));
stn->id = node_id++;
stn->parent = (Node*)malloc(sizeof(Node));
stn->suffix_node = (Node*)malloc(sizeof(Node));
stn->first_char_index = -1;
stn->last_char_index = -1;
stn->children_size = NODE_BASE_DEGREE;
stn->children_count = 0;
stn->children = (Node**)malloc(stn->children_size*sizeof(Node*));
stn->is_leaf = true;
stn->depth = 1;
return stn;
}
SuffixTree* createSuffixTree(char *str)
{
SuffixTree *st = (SuffixTree*)malloc(sizeof(SuffixTree));
st->root = createNode();
st->root->parent = (Node*)malloc(sizeof(Node));
st->root->parent->id = -1;
st->nodes_count = 1;
st->string = str;
makeTreeWithUkkonen(st);
return st;
}
makeTreeWithUkkonen is correct, I can display correct tree after createSuffixTree() call.
As GeoMad89 said, you malloc already existing nodes in the createNode() method.
If you change your createNode() code into this:
Node* createNode(Node* parent, Node* suffixNode){
Node *stn = (Node*)malloc(sizeof(Node));
stn->id = node_id++;
stn->parent = parent; //(Node*)malloc(sizeof(Node));
if(suffixNode != NULL)
stn->suffix_node = suffixNode; //(Node*)malloc(sizeof(Node));
stn->first_char_index = -1;
stn->last_char_index = -1;
stn->children_size = NODE_BASE_DEGREE;
stn->children_count = 0;
stn->children = (Node**)malloc(stn->children_size*sizeof(Node*));
if(parent != NULL){
parent->children[parent->children_count++] = stn;
parent->is_leaf = false;
}
stn->is_leaf = true;
stn->depth = 1;
return stn;
}
And if you try it with valgrind, using this toy main:
main(int argc, char** argv){
Node* root = createNode(NULL, NULL);
Node* node1 = createNode(root, NULL);
Node* node2 = createNode(root, NULL);
Node* node3 = createNode(node1, NULL);
deleteSubTree(root);
return 0;
}
You will see that all the malloc'd memory will be freed!
Needless to say, this code works only with NODE_BASE_DEGREE=2, otherwise, if you use a greater NODE_BASE_DEGREE value, you have to realloc the children array.
I have noticed that the leaf nodes have their children array not empty, because children_size is equal to NODE_BASE_DEGREE.
Try to delete the elements of the array in the leaves before eliminating them.
I have noticed two possible memory leaks:
In createNode, i suppose that the parent of the node that you going to create already exist, there is no need to malloc a space for it. But anyway you change the value of the pointer of parent in createSuffixTree, at least in the root of the tree, so this memory that you have allocated in createNode for parent is lost.
I don't know what suffix_node is, if is a node of the tree there is the same problem of the point one. But if is another node and so it is correct allocate memory, you don't freed when deleted the tree.
My program is supposed to read a postfix expression and convert it to infix and prefix using a tree implementation.
the pop() method always give the first element without errasing it and i can't figure out why. Any help will be apreciate.
//tree structur
typedef struct asa {
enum { number_exp,sous_exp_op } type;
union {
int child;
struct {
struct asa* left;
struct asa* right;
char oper; } tree;
} op;
} asa;
//stack
typedef struct stack {
int size;
struct {
asa * element;
struct stack* link;
}e;
} stack;
struct stack *top;
(...)
asa * pop(){
asa* e ;
stack * temp;
if(top->size == 0 ){
printf("ERR0R : empty stack\n");
exit (EXIT_FAILURE);
}
else if (top->size >= 1){
temp = top->e.link;
e= top->e.element;
top = temp;
}
return e;
}
void push(asa* node ){
if(top->size == 0 ){
top->e.element = node;
top->e.link = NULL;
top->size++;
}
else if (top->size > 0){
pile * next = (pile*) malloc(sizeof(top));
next = top;
top->e.element = node;
top->e.link = next;
top->size++;
}
}
Logs snapshot:
Your immediate problems are that you are discarding next as soon as you allocate it when top->size > 0 and that you are allocating the size for a pointer rather than for the whole struct. To fix them, replace next = top with top = next at the end of the function and fix the sizeof invocation:
else if (top->size > 0){
pile * next = (pile*) malloc(sizeof(*top));
next->e.element = node;
next->e.link = top;
next->size = top->size + 1;
top = next;
}
Also, this implementation of stack feels needlessly complex and error-prone. If you need the stack size, you should maintain the size independently of the nodes of the linked list, not in every individual node. The standard linked list idiom is to represent the empty list (stack) as NULL, so neither push nor pop need any extra code to check for empty stack:
typedef struct stack {
asa *element;
struct stack *next;
} stack;
void push(stack **head, asa *elem)
{
stack *new_head = malloc(sizeof(stack));
new_head->next = head;
new_head->elem = elem;
*head = new_head;
}
asa *pop(stack **head)
{
stack *old_head = *head;
asa *top_elem = old_head->elem;
*head = old_head->next;
free(old_head);
return top_elem;
}
I am working with a double linked list and I have run into a problem with my pop() function.
//QueueElement describe the block in the cache
typedef struct _queue_ele_
{
char *content; //the data of the block
struct _queue_ele_ *prev;
struct _queue_ele_ *next;
}QueueElement;
typedef struct _queue_
{
int queue_len;
int max_queue_size;
QueueElement *head;
QueueElement *tail;
}MyQueue;
The pop function works until there is an input of 2 elements ( I clear the queue by poping one by one and freeing the memory)
pop:
// head is removed and returned
QueueElement* pop(MyQueue* myqueue)
{
// if empty
if(myqueue->queue_len == 0) return NULL;
QueueElement *p = myqueue->head;
// if one element
if(myqueue->queue_len == 1)
{
myqueue->queue_len--;
myqueue->head = NULL;
myqueue->tail = NULL;
return p;
}
else
{
myqueue->queue_len--;
//remove the head from the queue
myqueue->head = myqueue->head->prev;
myqueue->head->next = NULL; //******************Seg Fault here
p->prev = NULL;
return p;
}
}
The error I get when there are two elements is a segmentation fault in line shown, but it works for queues with more. Why wont it let me assign NULL to myqueue->head->next???
Change this:
myqueue->head = myqueue->head->prev;
myqueue->head->next = NULL; //******************Seg Fault here
To:
myqueue->head = myqueue->head->prev;
if (myqueue->head != NULL) {
myqueue->head->next = NULL;
}
It is likely that you are trying to dereference a NULL pointer. It also would appear that you may have a memory leak from not calling free on the nodes you are deleting, but it is possible you do that elsewhere in the code.