strongly connected component in C - c

I am working on implementation of strongly connected component using Tarjan's algorithm. I am giving input as a linked list of nodes and edges. However, gcc compiler gives segmentation fault every time in the recursive function(where in the while loop I am checking for adjacent nodes of a vertex).
Any idea what's wrong in this code?
void strongconnect(int Vertex)
{
struct sc_node * Ver;
Ver = search_node(Vertex);
Ver->sc_index = ind; //accessing the index information of node
Ver->sc_lowlink = ind; // accessing the link information of node
//Ver->visited = 1;
ind++;
int w;
push(Vertex);
struct sc_node * to_link, *to_link1;
int to_lowlink,to_index;
int flowlink;
int min;
int from_index;
edge_trav = edge_head;
while(edge_trav != NULL) //accessing linked list of edges
{
if(edge_trav->from_vertex == Vertex)
{
to_link = search_node(edge_trav->to_vertex);
to_lowlink = to_link->sc_lowlink;
to_index = to_link->sc_index;
to_link1 = search_node(Vertex);
flowlink = to_link1->sc_lowlink;
from_index = to_link1->sc_index;
if(to_index == 0)
{ Vertex = to_link->sc_data;
printf("INSIDE RECURSION");
strongconnect(Vertex); // recursive loop
min = minimum(flowlink,to_lowlink);
to_link1->sc_lowlink = min;
}
else
{
min = minimum(flowlink, from_index);
to_link1->sc_lowlink = min;
} }
edge_trav = edge_trav->next;
}
Ver = search_node(Vertex);
if(Ver->sc_lowlink == Ver->sc_index)
{
do
{
w = pop();
printf("%d\t",w);
}while(w != Vertex);
}
}

I suggest you compile you program with gcc's -s and then run your program with valgrind. It's very useful memory leak checker. With it, you can figure out by yourself with is you program accessing an illegal memory position. As #Dogbert pointed, it looks you are dereferencing an NULL pointer.

Related

memory leak in adding and deleting dynamic list

I really need your help in this matter. I have these two functions that do the following:
copy face struct and add it to a list of faces (_face_list_entry_t)
copy a pointer of struct and add it to a list of pointers (fib_entry_t )
I created these two functions to dynamically allocate and add new items (faces and pointers) to their respected list. (I don't want the function of removing item)
I am currently facing a memory leak and I am not sure if allocating/reallocating/freeing the memory in them causes this issue. Below is the the two functions:
int8_t face_list_add(_face_list_entry_t** face_list, int8_t* face_list_size, _face_list_entry_t* face)
{
if (*face_list == NULL) {
*face_list = malloc(sizeof(_face_list_entry_t));
if (*face_list == NULL) {
DEBUG("fail to allocate memory for face list\n");
return -1;
}
*face_list_size = 1;
(*face_list)[0].id = face->id;
(*face_list)[0].type = face->type;
return 0;
} else {
// check for existing face entry
for (int i = 0; i < *face_list_size; ++i) {
if ((*face_list)[i].id == face->id) {
DEBUG("wildcard: same face exists in the fib entry\n");
return 1;
}
}
// need to add a new entry to the face list
_face_list_entry_t *list = (_face_list_entry_t*) realloc( *face_list, (*face_list_size + 1) * sizeof(_face_list_entry_t));
DEBUG("facelist size = %d\n", (*face_list_size + 1) * sizeof(_face_list_entry_t));
if (list == NULL) {
DEBUG("fail to reallocate memory for face list (size=%d)\n", *face_list_size);
return -1;
}
*face_list = list;
(*face_list)[*face_list_size].id = face->id;
(*face_list)[*face_list_size].type = face->type;
++(*face_list_size);
return 0;
}
}
int8_t pointer_list_add(fib_entry_t ***fib_list, int8_t *fib_list_size, fib_entry_t **fib)
{
if (*fib_list == NULL) {
*fib_list = malloc(sizeof(fib_entry_t *));
if (!*fib_list) {
DEBUG("fail to allocate memory for fib list\n");
return -1;
}
*fib_list_size = 1;
**fib_list = *fib;
return 0;
} else {
// check for existing fib entry
for (int i = 0; i < *fib_list_size; ++i) {
if ((*fib_list)[i] == *fib) {
DEBUG("same fib exists in the fib entry\n");
return 1;
}
}
// need to add a new entry to the fib list
fib_entry_t **list = (fib_entry_t **)realloc(*fib_list, (*fib_list_size + 1) * sizeof(fib_entry_t *));
if (!list) {
DEBUG("fail to reallocate memory for fib list (size=%d)\n", *fib_list_size);
return -1;
}
**fib_list = *list;
(*fib_list)[*fib_list_size] = *fib;
++(*fib_list_size);
return 0;
}
}
I call them like this:
res = face_list_add(&list_faces, &lst_faces_size, face);
res = pointer_list_add(&list_fibs, &list_fibs_size, &fib);
I delete the list like below. I don't want to delete the memory that each pointer is pointing to, I just want to delete the allocated memory for the list of pointers and the list of faces:
free(list_faces);
free(list_fibs);
Please let me know if I am doing it wrong or suggest a better way (low cost) as the device I am working on has a constrained capability, very low memory (256KB), and low process power, i.e. maintaining memory is crucial. Besides, usually, both lists are relatively small but in some cases can become bigger.
Your help is highly appreciated
Given the face_list_add() and pointer_list_add() functions presented and these calls that (re)allocate memory ...
res = face_list_add(&list_faces, &lst_faces_size, face);
res = pointer_list_add(&list_fibs, &list_fibs_size, &fib);
, these free() calls ...
free(list_faces);
free(list_fibs);
... are correct for for freeing the memory allocated by those functions. Or they would be, if the functions were correct. face_list_add() appears to be ok, but there is an error in realloc branch of pointer_list_add(), here:
**fib_list = *list;
That should be
*fib_list = list;
, analogous to
*fib_list = malloc(sizeof(fib_entry_t *));
in the initial allocation branch.

Height trie tree in C

I need to calculate the height of a trie tree in C
the node struct is as follows:
struct trie_cel {
char type; // 'I': internal / 'P': letter
struct trie_cel *child [HEIGHT_ALPHABET]; // use the function CHAR_TO_INDEX to get child node of each letter
};
typedef struct trie_cel no;
i'm trying to use recursion
if(r == NULL) return -1;
if(!r) return 0;
int alt = 0;
int heightM = 0;
no** i = r->child;
no** fim = i + (sizeof(r->child) / sizeof(no *));
while(i != end){
alt = height(r->child[i])+1;
if(alt > heightM){
heightM = alt;
}
}
return heightM;
However, my code is presented with the following problem, could anyone help me?
trie.cpp: In function ‘int altura(no*)’:
trie.cpp:146:32: error: invalid types ‘trie_cel* [27][no** {aka trie_cel**}]’ for array subscript
alt = height(r->child[i])+1;
^
chmod: cannot access 'vpl_execution': No such file or directory
I was able to calculate using "int" but i'd like to learn how to calculate using pointers
Maybe use the pointer directly 'height(*i)'. Or use pointer arithmetics to convert to integer type: 'i - r->child'
I believe this is how you should approach:
int trie_height(no *root) {
if (root == NULL) return -1;
int i, h = 0;
for (i = 0; i < HEIGHT_ALPHABET; i++) {
int res = 1 + trie_height(root->child[i]);
if (res > h)
h = res;
}
return h;
}
Since child is an array, you can't adress it's elements anything other than an integer. i isn't an integer in your code, so it wouldn't work. Also, you're doing nothing with fim after assigning it, so it's useless there.

C : Linked list value lost during execution

I am actually trying to implement a breadth-first-search algorithm in C, as an input I take any graph from a file and store all nodes and vertices in a structure.
Then I create an adjacency matrix, and run through all columns, push encountered nodes on a stack, pop them and so on till I have all the paths.
Still I have problems storing those paths in a linked list, and by problem I mean that sometimes, from some specific cases, I lose the last value of my stored path (one int array per link), which is quite surprising as it occurs only on paths of length 5 (I cannot test all lengths but up to 12 it seems OK).
It's weird, because these values are lost at function exit (I tried debugging using LLDB and in the function that creates the link, the last byte exists, but once I leave the function, it does not) and not all the time (1 out 10 execution all is fine).
To me this is a malloc issue, so I checked every single malloc of my program in order to solve (unsuccessfully) the problem. Checked all the variables and all seems fine, except for this 5 length case (I assume my program has a 'defect' that is only apparent in this case, but why ?).
I would gladly accept some help, as I just ran out of things to check.
Here is the code of the main BFS function :
void bfs(t_lemin *e)
{
t_path *save;
//set needed variables
set_bfs_base_var(e);
save = e->p;
while (paths_remain(e))
{
//Special Start-End case
if (e->map[e->nb_start][e->nb_end] == 1)
{
create_single(e);
break ;
}
e->x = e->nb_start;
reset_tab(e);
while (e->x != e->nb_end)
{
e->y = 0;
while (e->y < e->nb_rooms)
{
if (e->map[e->x][e->y] == 1 && !e->visited[e->y])
##push_on_stack the nodes
push_stack(e);
e->y++;
}
//go_to first elem on stack
e->x = e->stack[0];
if (e->x == e->nb_end || is_stack_empty(e->stack, e->nb_rooms - 1))
break ;
e->visited[e->x] = 1;
//set_it as visited than pop it
pop_stack(e, e->nb_rooms);
}
if (is_stack_empty(e->stack, e->nb_rooms - 1))
break ;
e->find_new[add_path(e)] = 1;
discover_more_paths(e, save);
}
print_paths(e, save);
e->p = save;
}
And here the 2 functions that stores the paths in a linked list :
void create_path(t_lemin *e, int *pa, int len)
{
int j;
j = 1;
//create_new_node if required
if (e->p->path)
{
if (!(e->p->next = malloc(sizeof(t_path))))
return ;
e->p = e->p->next;
}
//create_the_array_for_path_storing
e->p->path = malloc(sizeof(int) * len + 2);
e->p->next = NULL;
e->p->size_path = len + 2;
//copy_in_it
while (--len >= 0)
{
e->p->path[j++] = pa[len];
}
//copy_end_and_start_at_end_and_start
e->p->path[e->p->size_path - 1] = e->nb_end;
e->p->path[0] = e->nb_start;
e->nb_paths++;
}
int add_path(t_lemin *e)
{
int i;
int save;
int *path;
int next_path;
i = 0;
if (!(path = malloc(sizeof(int) * e->nb_rooms)))
exit(-1);
save = e->nb_end;
//in_order_to_save_the_path_i store the previous value of each node so I can find the path by iterating backward
next_path = -1;
while (e->prev[save] != e->nb_start)
{
path[i] = e->prev[save];
save = e->prev[save];
next_path = next_path == -1 && get_nb_links(e, path[i])
> 2 ? path[i] : -1;
i++;
}
//path_contains all values of the path except for start and end
save = i;
while (i < e->nb_rooms)
{
path[i] = 0;
i++;
}
create_path(e, path, save);
i = next_path == -1 ? path[0] : next_path;
//ft_printf("to_block : %d\n", i);
return (next_path == -1 ? path[0] : next_path);
}
If needed here is a clone of the entire repository, the issue can be seen running the program with maptest in the main directory : https://github.com/Caribou123/bfs_agesp.git
Make && ./lem_in < maptest
All paths must end by the last room, whereas in this case the value of the last room becomes 0. So the program outputs "start->room1->room2->....->start as the index value of start is 0.
Here is a look at my 'e', the main structure. (it's quite huge, don't be scared) :
typedef struct s_lemin
{
int x;
int y;
char *av;
int nb_ants;
int st;
int nd;
int nb_rooms;
int nb_paths;
int max_sizep;
int nb_links;
int nb_start;
int nb_end;
int **map;
int *stack;
int *visited;
int *prev;
int *find_new;
int maxy;
int maxx;
int minx;
int conti;
int miny;
char ***saa;
struct s_rooms *r;
struct s_ants *a;
struct s_rooms **table_r;
struct s_links *l;
struct s_hash **h;
struct s_rooms *start;
struct s_rooms *end;
struct s_info *i;
struct s_path *p;
struct s_path *select_p;
}
Thank you in advance for your help, and sorry if it's some stupid malloc that I somehow missed.
Artiom

graph implementation with adjacency lists in C

I just started learning C and as a self-learning excercise, I am implementing data structures and algos in C. Right now I am working on a graph and this is the data structure representation of it.
typedef int graphElementT;
typedef struct graphCDT *graphADT;
typedef struct vertexTag
{
graphElementT element;
int visited;
struct edgeTag *edges;
struct vertexTag *next;
} vertexT;
typedef struct edgeTag
{
int weight;
vertexT *connectsTo;
struct edgeTag *next;
} edgeT;
typedef struct graphCDT
{
vertexT *vertices;
} graphCDT;
To this graph I added a addVertex function.
int addVertex(graphADT graph, graphElementT value)
{
vertexT *new = malloc(sizeof(*new));
vertexT *vert;
new->element = value;
new->visited = 0;
new->edges = NULL;
new->next = NULL;
int i = 0;
for(vert=graph->vertices; vert->next != NULL; vert=vert->next)
{
if(vert->element == value)
{
printf("already exists\n");
return 0;
}
}
vert->next = new;
//free(new);
printf("\ninserted %d\n", vert->element);
return 1;
}
This works fine except for three things.
if the newly added vertex is the same as the last vertex in the list, it fails to see it. To prevent this i changed the for loop limiting condition to vert != NULL, but that gives a seg fault.
if i try to free the temporarily allocated pointer, it resets the memory pointer by the pointer and this adds an infinite loop at the end of the vertex list. Is there no way to free the pointer without writing over the memory it points to? Or is it not really needed to free the pointer?
Also would destroying the graph mean destroying every edge and vertices? or is there a better approach?
Also if this data structure for graph is not a good one and there are better implementations, i would appreciate that being pointed out.
1
If you change the limiting condition to vert!=NULL , and if the loop ends with vert==NULL ,i.e. ,the vertex to be added isn't present , then you will be reading next statement :
vert->next = new;
That means you are accesing the NULL ,vert pointer , hence the seg fault .
Now to allow checking if the last element isn't the vertex to be added ,and also to prevent seg fault ,do this :
for(vert=graph->vertices; vert->next != NULL; vert=vert->next)
{
if(vert->element == value)
{
printf("already exists\n");
return 0;
}
}
if(vert->element == value)
{
printf("already exists\n");
return 0;
}
vert->next = new;
2
The temporary "new" pointer is the memory location allocated to the Vertex you added .IT IS NOT to be freed ,as freeing it will mean that you deleted the vertex you just added :O .
3
Yes , detroying the graph essentialy means the same .
It is always a good practice to implement linked list as a adjacency list implementation of graph .Although you can always use a c++ "2 D Vector" to implement the same .
Here's a working addVertex function that you can use.
I am keeping the original declarations as it is.
I have added a main () to which you can give command line arguments to test.
int addVertex(graphADT graph, graphElementT value)
{
vertexT *tmpvert , *vert ;
vert=graph->vertices ;
/*check to see whether we really need to create a new vertex*/
tmpvert = vert;
while(tmpvert != NULL)
{
/* U can put a debug printf here to check what's there in graph:
* printf("tmpvert->elem=%d ", tmpvert->element);
*/
vert = tmpvert;
if(tmpvert->element == value)
return 0;
tmpvert=tmpvert->next ;
}
/*If we are here , then we HAVE to allocate memory and add to our graph.*/
tmpvert = (vertexT*)malloc(sizeof(vertexT));
if ( NULL == tmpvert )
return 0; /* malloc failure */
tmpvert->element = value;
tmpvert->visited = 0;
tmpvert->edges = NULL;
tmpvert->next = NULL;
if ( NULL == vert )
graph->vertices = tmpvert; /*Notice that I dont use virt=tmpvert */
else
vert->next = tmpvert; /*putting stuff in next is fine */
return 1;
/* Dont try printing vert->element here ..vert will be NULL first time */
/*return code for success is normally 0 others are error.
*That way you can have your printfs and error code
*handling outside this function.But its ok for a test code here */
}
Now for the main () snippet for testing :
int main (int argc , char* argv[]) {
graphADT graph ;
graph =(graphADT) malloc ( sizeof(struct graphCDT) );
graph->vertices = NULL;
while ( --argc >0)
{
int value = atoi(argv[argc]);
addVertex(graph,value);
}
}

Why am I getting a segmentation fault with this code?

Trying to make a simple rectangle/bin packer in C. Takes a given area and finds placement for any given size rectangle.
About after 4 recursions is when I get the segmentation fault.
#include <stdio.h>
#include <stdlib.h>
typedef struct node_type PackNode;
struct node_type {
int x , y;
int width , height;
int used;
struct node_type *left;
struct node_type *right;
};
typedef struct point_type PackPoint;
struct point_type {
int x,y;
};
PackNode _clone(PackNode *node) {
PackNode clone;
clone.used = 0;
clone.x = node->x;
clone.y = node->y;
clone.width = node->width;
clone.height= node->height;
clone.left = NULL;
clone.right= NULL;
return clone;
}
PackNode root;
int rcount;
PackPoint* recursiveFind(PackNode *node, int w, int h) {
PackPoint rp;
PackPoint *p = NULL;
rcount++;
printf ("rcount = %u\n", rcount);
//left is not null go to left, if left didn't work try right.
if (node->left!=NULL) {
//move down to left branch
p = recursiveFind(node->left, w, h);
if (p!=NULL) {
return p;
} else {
p = recursiveFind(node->right, w, h);
return p;
}
} else {
//If used just return null and possible go to the right branch;
if (node->used==1 || w > node->width || h > node->height) {
return p;
}
//if current node is exact size and hasn't been used it return the x,y of the mid-point of the rectangle
if (w==node->width && h == node->height) {
node->used=1;
rp.x = node->x+(w/2);
rp.y = node->y+(h/2);
p = &rp;
return p;
}
//If rectangle wasn't exact fit, create branches from cloning it's parent.
PackNode l_clone = _clone(node);
PackNode r_clone = _clone(node);
node->left = &l_clone;
node->right = &r_clone;
//adjust branches accordingly, split up the current unused areas
if ( (node->width - w) > (node->height - h) )
{
node->left->width = w;
node->right->x = node->x + w;
node->right->width = node->width - w;
} else {
node->left->height = h;
node->right->y = node->y + h;
node->right->height = node->height - h;
}
p = recursiveFind(node->left, w, h);
return p;
}
return p;
}
int main(void) {
root = malloc(
root.x=0;
root.y=0;
root.used=0;
root.width=1000;
root.height=1000;
root.left=NULL;
root.right=NULL;
int i;
PackPoint *pnt;
int rw;
int rh;
for (i=0;i<10;i++) {
rw = random()%20+1;
rh = random()%20+1;
pnt = recursiveFind(&root, rw, rh);
printf("pnt.x,y: %d,%d\n",pnt->x,pnt->y);
}
return 0;
}
if (node->left!=NULL) {
//move down to left branch
p = recursiveFind(node->left, w, h);
if (p!=NULL) {
return p;
} else {
p = recursiveFind(node->right, w, h);
You never check if node->right is NULL, so the next recursion may dereference NULL.
You're returning a pointer to a local variable in this case:
//if current node is exact size and hasn't been used it return the x,y of the mid-point of the rectangle
if (w==node->width && h == node->height) {
node->used=1;
rp.x = node->x+(w/2);
rp.y = node->y+(h/2);
p = &rp;
return p;
}
That's a big no-no. The local variable is no longer valid after the function returns, so the pointer you're returning points to stack memory that's now potentially being used for something else. When you start doing stuff with that, you're corrupting your stack, and your program will start behaving very erratically.
To fix this, you'll need to do one of a few things: (1) have recursiveFind() return a PackNode by value, instead of a pointer to a PackNode; (2) use a global/static PackNode instance, and return a pointer to that (note that this then makes recursiveFind() non-thread-safe); or (3) return a pointer to a dynamically allocated instance of a PackNode (e.g. allocated with malloc()); this then requires that the caller of recursiveFind() call free() on the returned pointer at some later point when it's no longer needed.
Likewise, this code is also wrong:
//If rectangle wasn't exact fit, create branches from cloning it's parent.
PackNode l_clone = _clone(node);
PackNode r_clone = _clone(node);
node->left = &l_clone;
node->right = &r_clone;
You need to allocate l_clone and r_clone on the heap, not on the stack, because again, as soon as this function returns, those node pointers will no longer be valid. I'd recommend having _clone() return a pointer to a PackNode (allocated with malloc()) instead of a full PackNode object by value. If you do that, though, the calling code needs to know to call free() on the returned pointer at some later point when the object is no longer needed.
[Also, identifiers at global scope beginning with an underscore are reserved by the implementation, so you should avoid using such names; you should rename _clone() to something like clone() or clonePackNode()].
Without looking closely at your code, you might try using a tool such as Valgrind or GDB to identify the line number/expression causing the segmentation fault. You can work backwards from there.
“Give a man a fish; you have fed him for today. Teach a man to fish; and you have fed him for a lifetime”

Resources