Home > Enterprise >  c segfault in function log_init
c segfault in function log_init

Time:10-06

I am trying to create a database in c and I am trying to figure out what is going on in a simplified version.
Now hear this: No matter what value I assign N to be (which is the size of database measured in logs) I get a segfault in the third entry,even if N is 1! (or 1000).
There is no way of knowing which chunk of prohibetted memory is parsed because all that gdb reports is the line of code that the exception occured.Seems like debugging is useless here.What am I doing wrong? Thank you all in advance.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 1 //the initial size of the database
#define STRLIM 30 

typedef struct log{
    int id;
}log_t;

typedef struct index{
    int sarcount;
    int sarcap;
}index_t;

log_t* init_log(log_t** log,index_t* index);
int printList(log_t** log,index_t* index);
int menu(void);

log_t* init_log(log_t** cat,index_t* index){
    cat[index->sarcount]->id=index->sarcount;
    
    index->sarcount  ;
    return *cat;
}

int menu(void){
    printf("1. Insert a new log\n");
    printf("5. Exit\n");   
    printf("6. Print the list\n");
    return 0;
}//just prints the menu 

int printList(log_t** cat,index_t* index){
    int i=0;
    for(i=0;i<index->sarcount;i  ){
        printf("#%dID:%d\n",i,cat[i]->id);
    }
}

int main(int argc, char const *argv[])
{  
    log_t* log=malloc(sizeof(log_t)*N);
        if(!log){
            perror("failed to malloc:");
            exit(EXIT_FAILURE);
        }
    index_t* index=malloc(sizeof(index_t));
    index->sarcount=0;


int choice=0;
      while(1){
        menu();
          scanf("%d", &choice);
    if(choice==1){
       printf("enter a log\n");     
    log=init_log(&log,index);  
    }
   
    if(choice==5){
        printf("exiting now\n");
        exit(0);
    }
    if(choice==6){
        system("clear");
        printf("printing all existing movies:\n");
        printList(&log,index);
     }
  }//end of while 
    return 0;
}


CodePudding user response:

I think the problem is in init_log and printList function.

Try the below changes

In init_log

change cat[index->sarcount]->id=index->sarcount; to (*cat index->sarcount)->id = index->sarcount;

In printList

change printf("#%dID:%d\n",i,cat[i]->id); to printf("#%dID:%d\n",i,(*cat i)->id);

Also I would suggest you to change the structs like below (remove log and index name):

typedef struct{
    int id;
}log_t;

typedef struct{
    int sarcount;
    int sarcap;
}index_t;

CodePudding user response:

I'm not even sure of the right terminology to describe it, but you're abstracting one more level than you should be passing the parameters to your functions. When you do

log_t* log=malloc(sizeof(log_t)*N);

You're reserving memory to N log_ts, and log points to them:

           ______________________________________
log -----> | log_t 0 | log_t 1 | ... | log_t N-1|
           --------------------------------------

When you pass &log to init_log (and printList), you're passing a pointer of log to those functions. So you have:

cat ------> log -------> (as above)

Now, when you do cat[index->sarcount], you're dereferencing an index of cat. However, cat only has a length of 1, it only points to one log_t*. Anything more than cat[0] is out of bounds. log is the pointer that points to log_t objects with dimensionality beyond 0. So you need to do something like

cat ------> log[index-sarcount]

to select the appropriate log. As suggested in the other answer, you could do that like:

(*cat)[index->sarcount].id = index->sarcount;

Here, (*cat) always dereferences to the first (and only) instance of log_t* it points to, and [index->sarcount] dereferences the actual log_t object (max of N-1) you want to modify.

But, having said all that, that extra level of indirection is really unnecessary. I would change your function prototypes to

void init_log(log_t** log,index_t* index); // well ok, still using log_t** here. Don't have to, but I consider that better practice than returning a log_t
void printList(log_t* log,index_t* index);

And then these functions would look like:

void init_log(log_t** cat,index_t* index){
    (*cat)[index->sarcount].id=index->sarcount;
    
    index->sarcount  ;
}

void printList(log_t* cat,index_t* index){
    int i=0;
    for(i=0;i<index->sarcount;i  ){
        printf("#%dID:%d\n",i,cat[i].id);
        // for your current `printList` function, this would need to be
        //printf("#dID:%d\n", i, (*cat)[i].id);
    }
}

And then you would call them like

init_log(&log,index);
printList(log,index);

An example

  • Related