C List Segmentation Fault - c

Hello guys i got a problem while running this code:
trying to run the printf in the comment i got a segfault, also without that i dont see my listed printed ad the function Stampa should do.
Probably i am missing something with pointers
#include <stdio.h>
#include <stdlib.h>
struct nodo { // double linked list
int info;
struct nodo *prec;
struct nodo *succ;
};
typedef struct nodo nodo;
struct nodo *Crealista(void);
void Stampa (struct nodo *nodo);
int main(int argc, const char * argv[]) {
struct nodo *p;
p = Crealista();
// printf("%d",p->succ->info);
Stampa(p);
return 0;
}
// this funct should print the whole list
void Stampa (struct nodo *p) {
while (p->succ != NULL ) {
printf("Value : %d \n", p->info);
p = p->succ;
}
}
// this funct should create list with n members and return a pointer to the first element
struct nodo *Crealista(void) {
struct nodo *p, *primo, *back;
int i, n;
p = NULL;
primo = NULL;
back = NULL;
printf("Numero di elementi: ");
scanf("%d", &n);
printf("inserisci %d numeri interi positivi: ", n);
for (i=0; i<n; i++) {
p = malloc(sizeof(struct nodo));
scanf("%d", &p->info);
p->prec = back;
p->succ = NULL;
back = p;
}
primo = p;
while (primo->prec != NULL) { primo = primo->prec;}
return(primo);
}

Stampa()
Let's look at what we want to do when we print the entire list:
If the current element is valid, then we want to print it.
Then, we want to iterate to the next element, and continue this loop.
That's not what your code does. Your code looks to see if the current element has a successor, and if it does, we print the current element's value.
That function should actually be:
void Stampa (struct nodo *p) {
while (p != NULL ) {
printf("Value: %d\n", p->info);
p = p->succ;
}
}
Crealista()
If you tell Crealista() to create a list of 0 elements, your final while loop will exhibit undefined behavior.
If you tell Crealista() to create a list of less than 2 elements, your commented printf() in main() will cause undefined behavior (if it was uncommented).
Doubly Linked Lists
You never update the value of nodo->succ. You only update the value of nodo->prev. Here's one example of how to do that:
if (p->prec)
p->prec->succ = p;
Putting all of this together
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct nodo {
int info;
struct nodo *prec;
struct nodo *succ;
};
typedef struct nodo nodo;
struct nodo *Crealista(void);
void Stampa (struct nodo *nodo);
int main(int argc, const char * argv[]) {
struct nodo *p;
p = Crealista();
Stampa(p);
}
// Print the list
void Stampa (struct nodo *p) {
while (p != NULL ) {
printf("Value: %d \n", p->info);
p = p->succ;
}
}
// Create a list of n elements
struct nodo *Crealista(void) {
int i, n;
struct nodo *p = NULL;
struct nodo *primo = NULL;
struct nodo *back = NULL;
printf("Numero di elementi: ");
scanf("%d", &n);
assert(n != 0);
printf("inserisci %d numeri interi positivi: ", n);
for (i=0; i<n; i++) {
p = malloc(sizeof(struct nodo));
scanf("%d", &p->info);
p->prec = back;
p->succ = NULL;
if (p->prec)
p->prec->succ = p;
back = p;
}
primo = p;
while (primo != NULL && primo->prec != NULL)
primo = primo->prec;
return primo;
}
Which when run...
Numero di elementi: 5
inserisci 5 numeri interi positivi: 1 2 3 4 5
Value: 1
Value: 2
Value: 3
Value: 4
Value: 5

The printf() call you have commented out will always exhibit undefined behavior when p->succ is NULL, as it will be when p points to the last (or only) element of the list. In that case, although the behavior is formally "undefined", it is quite likely to manifest as a segmentation fault.

In stampa add check
while(p!=NULL)
{
printf("Value %d",p->info);
p=p->succ;
}
You are probably accessing it when it is not allocated. Check it this way there is no problem if it reaches a null value also. And initial null value will not cause problem also(if used).
I have modified your code
// this funct should create list with n members and return a pointer to the first element
struct nodo *Crealista(void) {
struct nodo *p, *primo, *back;
int i, n;
p = NULL;
primo = NULL;
back = NULL;
printf("Numero di elementi: ");
scanf("%d", &n);
printf("inserisci %d numeri interi positivi: ", n);
p = (struct nodo *)malloc(sizeof(struct nodo));
scanf("%d", &p->info);
p->prec = back;
p->succ = NULL;
back = p;
for (i=1; i<n; i++) {
p = (struct nodo *)malloc(sizeof(struct nodo));
scanf("%d", &p->info);
p->prec = back;
p->prec->succ=p;
p->succ = NULL;
back = p;
}
primo = p;
while (primo->prec != NULL) { primo = primo->prec;}
return(primo);
}
You are not setting the succ pointer of previous node correctly. That is what causing you the problem. Check now.

Related

Item extraction from a list in C

I wrote a function to delete and extract an Item from a list following the usual algorithm for extraction, but while it scans the list it deletes all the items before the searched element.
I am probably missing some pointer being dereferenced but I can't really see where...
Thank you in advance for the help.
Here's the full code.
//DATA STRUCTURE
typedef struct{//EQUIPMENT
int inUse;
object **arrEquip;
}equip;
typedef struct{//PG
char code[MAXL];
char name[MAXL];
char class[MAXL];
equip equip_t;
stats stats_t;
}pg;
typedef struct nodePg theNodePg, *link;
struct nodePg{ //NODE
pg pg_t;
link next;
};
typedef struct{//LIST WRAPPER
link head;
link tail;
int nPg;
}tabPg;
int main(){
tabPg tabPg_t;
tabInv tabInv_t;
int choice;
tabPg_t.head = NULL;
tabPg_t.nPg = 0;
do{
printMenu(&choice);
runSelectedFun(&tabPg_t, &tabInv_t, choice);
}while(choice != 0);
return 0;
}
void runSelectedFun(tabPg *tabPg_t, tabInv *tabInv_t, int choice){
//[...]
pgExtraction(&tabPg_t->head);
//[...]
}
void pgExtraction(link *head){//eliminarlo dalla lista effettivamente
char toBeDeleted[MAXL];
theNodePg deleted;
int flag = 0;
printf("\nInserisci il codice del personaggio da eliminare");
scanf("%s", toBeDeleted);
deleted = extraction(head, toBeDeleted, &flag);
if(flag == 1){
printf("\nPersonaggio %s eliminato con successo!", deleted.pg_t.code);
}
else printf("\nIl codice inserito non ha corrispondenze all'interno della lista PG!\n");
}
theNodePg extraction(link *head, char *code, int *flag){
link *xp,t;
theNodePg deletedPg = {0};
for (xp = head; xp != NULL; xp = &(*xp)->next) {
if (strcmp((*xp)->pg_t.code, code) == 0) {
t = (*xp);
*xp = (*xp)->next;//eliminazione
deletedPg = *t;
free(t);
*flag = 1;
break;
}
}
return deletedPg;
}

Fill value by value a char *

I'm trying to fill a char *info inside a struct nodo;
This is struct :
struct nodo {
char *info;
struct nodo *prec;
struct nodo *succ;
};
typedef struct nodo nodo;
And this is whole function :
nodo *q,*t = NULL,*head = NULL;
int i, nodi=0 ;
char *c = a, *k = a;
while ( *c != '\0') {
if (*c == ' ')
nodi++;
c++;
}
for (i = 0; nodi != 0; i++) {
if (i == 0){
head = CreateFirstNodo();
t = head;}
if (i == 1)
q = CreateSecondNodo(head);
else
q = CreateNNodo(head);
nodi--;
}
char *k = a;
int i = 0;
while ( *k != '\0' )
{
if (*k == ' ' )
{
head = head->succ;
i = 0;
}
head->info[i] = *k; // ERROR EXC BAD ACCESS
i++;
k++;
}
return t;
}
k is a char* and should scroll the char[] to which is assigned and should copy any of his values to the proper place in head->info[i] which is char *info in struct
if k hits a space, the nodo goes to the next nodo and the 'i' become 0 again since i need a word filled in each nodo.
BUT this code shows error EXC BAD ACCESS in the marked line.
Here are the 3 CreateNodo functions:
nodo *CreateFirstNodo() {
nodo *q;
q = malloc(sizeof(nodo));
q->prec = NULL;
q->succ = NULL;
return q;
}
nodo *CreateSecondNodo(nodo *head) {
nodo *q;
q = malloc(sizeof(nodo));
q->succ = NULL;
q->prec = head;
head->succ = q;
return q;
}
nodo *CreateNNodo(nodo *head) {
nodo *q;
while (head->succ != NULL) {
head = head ->succ;
}
q = malloc(sizeof(nodo));
q->succ = NULL;
q->prec = head;
head->succ = q;
return q;
EDIT: sorry for lacking code.
You're attempting to dereference an uninitialized pointer, probably (an initialization is not shown).
When you access info[i] what it does is add info + i and use that as an address to find a char. If info has an invalid value (such as NULL), then you get the error you see.
You probably need to initialize info with something like info = malloc(size_i_want), but it's hard to see what you're trying to achieve here.
The reason you get EXC BAD ACCESS is because you never actually allocate memory for info. In your struct nodo you have info defined to be a pointer to a character, but you never have any memory allocated for it.
Depending on how big your input could be you could either do char info[256] (or whatever size you want) or you could calloc the amount of space you want in Createxxxx functions.
Additionally, you really only need one Create function. I would do something like this:
nodo *CreateNodo(nodo *head)
{
nodo *q;
q = calloc(1, sizeof(nodo));
if (q) {
//assume info should be 256 chars
q->info = calloc(256, sizeof(char));
if (!q->info) {
free(q);
return NULL;
}
q->succ = NULL;
q->prec = NULL;
if (head) {
while (head->succ != NULL) {
head = head->succ;
}
q->prec = head;
head->succ = q;
}
return (q);
}
That way you only have 1 function to debug/fix.

Filling Char* in struct field (list)

I'm having troubles passing by working on a list with "int" keys to a "char *" keys.
the struct looks like :
struct nodo {
char *info;
struct nodo *prec;
struct nodo *succ;
};
typedef struct nodo nodo;
and I'm trying to use a function i used a lot to fill a struct with int or float fields (adapted obviously):
struct nodo *Crealista(void) {
struct nodo *p, *primo, *back;
int i, n;
p = NULL;
primo = NULL;
back = NULL;
printf("Numero di elementi: ");
scanf("%d", &n);
assert(n!=0);
printf("inserisci %d numeri interi positivi: ", n);
for (i=0; i<n; i++) {
p = malloc(sizeof(struct nodo));
scanf("%c" /* or maybe s? i need a string for each nodo... */, p->info);
// i feel this is the line that needs some more work
p->prec = back;
p->succ = NULL;
if (p->prec)
p->prec->succ = p;
back = p;
}
primo = p;
while (primo != NULL && primo->prec != NULL)
primo = primo->prec;
return primo;
}
Any suggestions?
Just add & in scanf in the line you mentioned,
scanf(" %c", &p->info);
and give a space before %c in format string to " %c" so that it display text in format you want.

What does it means when I can't go inside a function? [C]

I'm trying to merge (alterning) two lists and create a third list without adding new nodes (question here). The code executes without errors or warnings but it seems to not entering into the function AlternateLists(), since is not printing the "Inside the function" string. What do you think it means? Can you give me a quick review and/or an expalanation to my code/problem?
Thanks..
#include <stdio.h>
#include <stdlib.h>
struct nodo {
int inf;
struct nodo *succ;
struct nodo *prec;
};
typedef struct nodo nodo;
nodo *RicercaPosizione( nodo *a, int i );
nodo *Inserisci(nodo *a, int i, int x);
nodo* AlternateLists(nodo* list1, nodo* list2);
void *MostraLista(nodo *a);
int main(){
nodo *lista1=NULL;
nodo *lista2=NULL;
nodo *lista3=NULL;
int numeri[]={1,2,3,4};
int numeri2[]={5,6,7,8};
int i=0;
while(i!=4){
printf("%d",i);
lista1=Inserisci(lista1,i, numeri[i]);
i++;
}
printf("lista1 \n\n");
MostraLista(lista1);
lista2=lista1;
printf("lista2 \n\n");
MostraLista(lista2);
printf("\n\nlista3 \n\n");
lista3=AlternateLists(lista1,lista2);
MostraLista(lista3);
}
nodo* AlternateLists(nodo* l1, nodo* l2){
printf("\n\n Inside the fuction");
// Check if arrays are != NULL
if(!l1 && !l2) return NULL;
if(!l1) return l2;
if(!l2) return l1;
//----------------------
nodo* c1 = l1;
nodo* c2 = l2;
nodo* next;
nodo* next2;
while(c1){
next = c1->succ;
if(c2){ // check to make sure there are still nodes in array2
c1->succ = c2;
next2 = c2->succ;
c2->succ = next;
c2 = next2;
}else{
c1->succ = next;
}
c1 = next;
}
while(c2){ //if there are more nodes in list 2 then there are in list 1
c1->succ = c2;
c2 = c2->succ;
c1 = c2;
}
return l1;
}
//Insert etc
nodo *Inserisci(nodo *a, int i, int x){
nodo *q, *p;
if ( i == 0 ){
q = malloc(sizeof(nodo));
q->succ = a; q->prec = NULL;
q->inf = x;
if (a != NULL)
a->prec = q;
a = q;
} else {
p = RicercaPosizione( a, i-1);
if (p != NULL){
q = malloc(sizeof(nodo));
q->inf = x;
q->succ = p->succ;
q->prec = p;
if ( p->succ != NULL)
p->succ->prec = q;
p->succ = q;
}
}
return a;
}
nodo *RicercaPosizione( nodo *a, int i ){
nodo *p = a;
int j = 0;
while ( j < i && p != NULL){
p = p->succ;
j = j+1;
}
return p;
}
void *MostraLista(nodo *a){
nodo *p = a;
while ( p != NULL ){
printf("%d, ", p->inf);
p = p->succ;
}
printf("\n");
}
Use a debugger:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400810 in AlternateLists (l1=0x601010, l2=0x601010) at demo.c:67
67 c1->succ = c2;
The problem:
while(c1){
...
}
/* At this point c1 is NULL */
while(c2){
c1->succ = c2; /* Boom */
c2 = c2->succ;
c1 = c2;
}
Since you showed some interest in learning to debug, I'll try to answer your question.
If a function that should be entered unconditionally, such as 'AlternateLists' in your code, is not entered, there are some possible reasons:
1) The process crashed before it got to the call. A segfault, or other serious error that comes to the attention of the OS, will terminate your process, usually with an error message of some sort.
2) The process/thread got blocked indefinitely before the call, or asked for such a long sleep that it was effectively blocked. In that case, CPU use for that thread will be 0.
3) The process/thread got stuck in an infinite CPU loop before the call, or a loop so long that it seems infinite. In that case, CPU use for that thread will be 100%.
Found the problem :)
Thanks to everybody for the help!
The problem was when I was trying to copy the list in the main.
printf("lista1 \n\n");
MostraLista(lista1);
lista2=lista1; \\This line was the problem..
printf("lista2 \n\n");
MostraLista(lista2);
printf("\n\nlista3 \n\n");
lista3=AlternateLists(lista1,lista2);
MostraLista(lista3);

pointing wrong list member

it may be a nooby question, but can you explain me why running this i get printed the last member of the list instead of the first? am i missing something?
struct nodo {
int info;
struct nodo *prec;
struct nodo *succ;
} ;
typedef struct nodo nodo;
nodo *leggi_lista(void);
int main (void) {
struct nodo *q;
q= NULL;
q=leggi_lista();
printf("%d\n\n", q->info); //should print first member of the list
return 0;
}
nodo *leggi_lista(void) { //creating list
nodo *p, *primo=NULL;
int i, n;
printf("Numero di elementi: ");
scanf("%d", &n);
printf("Inserisci %d numeri: ", n);
for (i=0; i<n; i++) {
p = malloc(sizeof(struct nodo));
scanf("%d", &p->info);
p->succ = primo;
primo = p;
}
return (primo) ;}
aaand i dunno what else i can add the post helper is bullying me :(
You are returning primo from the function which holds the value in p and this is got by the last malloc() and obviously you see the last value being printed out.
You need to fix your function to create the list. You need to keep your list's head intact and return the head from the function and print from head to end of list.

Resources