In that case, the chances are that st->title is an invalid pointer which
isn't null. Say, a pointer to memory that's already been freed, or
otherwise to an object which no longer exists. Another common source
would be that the pointer object itself got overwritten such that it's
no longer a meaningful pointer.
Function list_remove_element_by_id() was one which was causing problems,
I think now it is working fine. See any problem ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct sq_struct
{
char title[100+1];
struct sq_struct* next;
};
struct sq_list
{
struct sq_struct* head;
struct sq_struct* tail;
};
struct sq_struct* list_add_element( struct sq_list*, const char* t);
struct sq_list* list_remove_element(struct sq_list*);
struct sq_list* list_remove_element_by_id(struct sq_list*, const char* );
struct sq_list* list_new(void);
struct sq_list* list_free( struct sq_list* );
void list_print( const struct sq_list* );
void list_print_element(const struct sq_struct* );
int main(void)
{
struct sq_list* mt = NULL;
struct sq_struct* tmp = malloc(1 * sizeof(*tmp));
if(NULL == tmp)
{
printf("Out of Memory\n");
exit(EXIT_FAILURE);
}
mt = list_new();
list_add_element(mt, "1");
list_add_element(mt, "2");
list_add_element(mt, "3");
list_add_element(mt, "4");
list_print(mt);
list_remove_element_by_id(mt, "3");
list_remove_element_by_id(mt, "1");
list_print(mt);
list_free(mt); /* always remember to free() the malloc()ed memory */
free(mt); /* free(), list is kept separate from free()ing the
structure, I think its a good design */
mt = NULL; /* after free() always set that pointer to NULL, C
will run havoc on you if you try to use a dangling pointer */
list_print(mt);
free(tmp);
printf("everything free()ed\n");
return 0;
}
/* Will always return the pointer */
struct sq_struct* list_add_element(struct sq_list* s, const char* t)
{
struct sq_struct* retp;
struct sq_struct* p;
if(NULL == s || NULL == t)
{
fprintf(stderr, "IN: %s @%d: NULL Args", __FILE__, __LINE__);
return NULL;
}
p = malloc(1 * sizeof *p);
if( NULL == p )
{
fprintf(stderr, "IN %s, %s: malloc() failed\n", __FILE__,
"list_add");
retp = NULL;
}
else
{
strcpy(p->title, t);
p->next = NULL;
if( NULL == s->head && NULL == s->tail )
{
/* printf("Empty list, adding p->num: %d\n\n", p->num); */
s->head = s->tail = p;
retp = p;
}
else if( NULL == s->head || NULL == s->tail )
{
fprintf(stderr, "There is something seriously wrong with your
assignment of head/tail to the list\n");
free(p);
retp = NULL;
}
else
{
/* printf("List not empty, adding element to tail\n"); */
s->tail->next = p;
s->tail = p;
retp = p;
}
}
return retp;
}
struct sq_list* list_remove_element(struct sq_list* s)
{
struct sq_list* retp;
struct sq_struct* h;
struct sq_struct* nx;
if(NULL == s)
{
printf("IN: %s @%d: Invalid Args\n", __FILE__, __LINE__);
retp = NULL;
}
else if(NULL == s->head)
{
printf("IN: %s %d: Empty List\n", __FILE__, __LINE__);
retp = s;
}
else
{
h = s->head;
nx = h->next;
printf("Removing %s\n", h->title);
s->head = nx;
free(h);
if(NULL == s->head) s->tail = s->head; /* Means last element was
removed */
retp = s;
}
return retp;
}
/* Ugliest of the Hacks I have evr done. Queue (FIFO) is not the right
data structure to use if I am
removing elements from anywhere but top */
struct sq_list* list_remove_element_by_id(struct sq_list* s, const char*
title )
{
struct sq_struct* h;
struct sq_struct* prv;
struct sq_struct* nx;
if( NULL == s || NULL == title)
{
printf("IN: %s @%d: Invalid Args\n", __func__, __LINE__);
return NULL;
}
else if( NULL == s->head && NULL == s->tail )
{
printf("IN: %s @%d: Well, List is empty\n", __func__, __LINE__);
return NULL;
}
else if( NULL == s->head || NULL == s->tail )
{
printf("IN: %s @%d: ", __func__, __LINE__);
printf("There is something seriously wrong with your list\n");
printf("One of the head/tail is empty while other is not \n");
return NULL;
}
for(h = s->head, prv = NULL; h; h = h->next)
{
if(NULL == h->title)
{
printf("IN: %s @%d: *ERROR* struct exists but ID is NULL :-/",
__func__, __LINE__);
}
else
{
if(0 == strcmp(h->title, title))
{
printf("IN: %s @ %d: Removing %s\n", __FILE__, __LINE__, h-
nx = h->next;
free(h);
if(NULL == prv) /* means we are deleting head */
{
s->head = nx;
}
else
{
prv->next = nx;
}
break;
}
}
prv = h;
}
return s;
}
/* ---------------------- small helper fucntions
---------------------------------- */
struct sq_list* list_free( struct sq_list* s )
{
if(NULL == s)
{
printf("NULL args, nothing to free\n");
return NULL;
}
while( s->head )
{
list_remove_element(s);
}
return s;
}
struct sq_list* list_new(void)
{
struct sq_list* p = malloc( 1 * sizeof(*p));
if( NULL == p )
{
printf("LINE: %d, malloc() failed\n", __LINE__);
}
p->head = p->tail = NULL;
return p;
}
void list_print( const struct sq_list* ps )
{
struct sq_struct* p = NULL;
if( ps )
{
for( p = ps->head; p; p = p->next )
{
list_print_element(p);
}
}
printf("------------------\n");
}
void list_print_element(const struct sq_struct* p )
{
if( p )
{
printf("title: %s\n", p->title);
}
else
{
printf("Can not print NULL struct \n");
}
}
=========================== OUTPUT ============================
[arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra strange-queue.c
[arnuld@dune programs]$ ./a.out
title: 1
title: 2
title: 3
title: 4
------------------
IN: strange-queue.c @ 186: Removing 3
IN: strange-queue.c @ 186: Removing 1
title: 2
title: 4