c segfault in function log_init



我试图在c中创建一个数据库,我试图弄清楚在简化版本中发生了什么。
现在听我说:无论我给N赋什么值(这是日志中测量的数据库大小),我都会在第三个条目中得到一个段错误,即使N是1!(或1000)。
没有办法知道哪块被禁止的内存被解析,因为所有gdb报告的都是发生异常的代码行。似乎调试在这里是无用的。我做错了什么?提前感谢大家。

#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 logn");
printf("5. Exitn");   
printf("6. Print the listn");
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:%dn",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 logn");     
log=init_log(&log,index);  
}

if(choice==5){
printf("exiting nown");
exit(0);
}
if(choice==6){
system("clear");
printf("printing all existing movies:n");
printList(&log,index);
}
}//end of while 
return 0;
}

我甚至不确定用什么术语来描述它,但是您比应该将参数传递给函数的级别多了一个抽象级别。当你做

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

您为Nlog_ts保留内存,log指向它们:

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

当您将&log传递给init_log(和printList)时,您将log指针传递给这些函数。所以你有:

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

现在,当您执行cat[index->sarcount]时,您正在解引用cat的索引。然而,cat的长度只有1,它只指向一个log_t*。任何超过cat[0]的都是越界的。log是指向维度大于0的log_t对象的指针。所以你需要输入

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

选择适当的日志。正如另一个答案所建议的那样,您可以这样做:

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

这里,(*cat)总是解除对它所指向的log_t*的第一个(也是唯一一个)实例的引用,而[index->sarcount]解除对实际的log_t对象(N-1的最大值)的引用。

但是,说了这么多,额外的间接层次真的是不必要的。我会把你的函数原型改成

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);

然后这些函数看起来像:

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:%dn",i,cat[i].id);
// for your current `printList` function, this would need to be
//printf("#dID:%dn", i, (*cat)[i].id);
}
}

然后叫它们

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

一个例子

我认为问题是在init_log和printList函数

尝试以下更改

在init_log

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

在printList

changeprintf("#%dID:%dn",i,cat[i]->id);toprintf("#%dID:%dn",i,(*cat + i)->id);

我还建议你像下面这样改变结构(删除日志和索引名称):

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

最新更新