我试图在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);
您为N
log_t
s保留内存,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;