用Ubuntu20.04.5的vscode运行一个读取文件中的数据进行搜索的代码,报错:
出现异常。
Segmentation fault
错误如图,
程序大意是把txt文件中存储的树读取出来,找到指定的叶子节点,修改其中的数据,因为父节点中参数的值由其左右子节点中参数的值生成,修改叶子节点的值需要通过父节点指针找到父节点并修改参数的值,直至根节点。
程序运行到此函数中时,经过几次if之后发生错误。文件里的数据应该不会太大呀,之前搜索树上的数据的时候文件规模为2000都没事,更新的时候500应该不会是栈溢出吧,网上找了一圈,出现这种错误的原因有很多,感觉应该是程序本身有问题,找了一下午没找到原因,有人能发现问题所在并帮助我解决问题吗?
代码头文件define_update.h如下:
/***
* This code .h file define size and struct used.
*/
#define FILE_SIZE 500//支持的文件数量,根据需要改
#define DICT_SIZE 60//支持的数据长度
#define MATRIXinv_PATH "./Matrix/Matrix60inv.txt"//加密的可逆矩阵其逆矩阵的位置(60表示其维度)
#define MATRIX_PATH "./Matrix/Matrix60trans.txt"//加密的可逆矩阵其转置的位置
#define Sk_PATH "./Sk.txt"//安全kNN加密参数——加密向量的位置
/*注意上述路径要根据自己文件的放置情况进行修改,不然可能会出现“ERROR: GDB exited unexpectedly. Debugging will now abort.“
或者“Aborted (core dumped)”的错误*/
// struct of node
typedef struct tree_node {
int ID; // node ID
double NSAB[DICT_SIZE]; // index data(非敏感属性关键词布隆过滤器)
double uSAB[DICT_SIZE];// unecrypted SAB
double SAB[2][DICT_SIZE]; // index data(敏感属性关键词布隆过滤器)
struct tree_node *Pl; // pointer to left node
struct tree_node *Pr; // pointer to right node
struct tree_node *Pf; // pointer to father node
int Lid; // pointer to document, use document's label here
} Node;
运行出错的程序del_update_index_tree.cpp如下:
//在索引树上搜索单个不包含敏感属性关键词
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include "define_update.h"
/***
* This code read the tree from file and do search.
*/
// File data tmp
double B1[FILE_SIZE][DICT_SIZE];//存放从文件中读取的非敏感属性布隆过滤器的值
double B2[FILE_SIZE][DICT_SIZE];//存放从文件中读取的敏感属性布隆过滤器的值,因为涉及后续会涉及加密,故类型定为double
double M[2][DICT_SIZE][DICT_SIZE]={0.0};//存放从文件中读取的加密矩阵
double SAB[2][DICT_SIZE];//暂时存放加密的布隆过滤器以备后续输入到节点的参数中
int Sk[DICT_SIZE]; // encryption vector
// struct of queue
Node queue[FILE_SIZE*2];
int front = 0, rear = -1, itemCount = 0;
Node *insert(Node *data) {
if( itemCount != FILE_SIZE*2 ) {
if( rear == FILE_SIZE*2-1 )
rear = -1;
queue[++rear] = *data;
itemCount++;
}
return &queue[rear];
}
Node *removeData() {
Node *data = &queue[front++];
if( front == FILE_SIZE*2 )
front = 0;
itemCount--;
return data;
}
// read tree from file,注意此部分读入顺序要与生成索引树的参数顺序一样
Node *file2tree( FILE *fp ) {
if( feof(fp) != 0 ) return NULL;
int i, l, r, f;
Node tn;
// ID
fscanf(fp, "%d ", &tn.ID);
// NSAB
for( i = 0; i < DICT_SIZE; i++ ) {
fscanf(fp, "%lf ", &tn.NSAB[i]);
}
// SAB
for( i = 0; i < DICT_SIZE; i++ ) {
fscanf(fp, "%lf ", &tn.uSAB[i]);
}
// pointer
fscanf(fp, "%d %d %d", &l, &r, &f);
// Lid
fscanf(fp, "%d ", &tn.Lid);
// recursive call
if( l != -1 )
tn.Pl = file2tree( fp );
else
tn.Pl = NULL;
if( r != -1 )
tn.Pr = file2tree( fp );
else
tn.Pr = NULL;
// check left and right child's ID
if( (tn.Pl != NULL && l != tn.Pl->ID)
|| (tn.Pr != NULL && r != tn.Pr->ID ) ) {
printf("Error at reading Node %3d from file\n", tn.ID);
}
return insert(&tn);
}
void addparent(Node *root,Node *q)
{
if(root!=NULL)
{
root->Pf=q;
q=root;
addparent(root->Pl,q);
addparent(root->Pr,q);
}
}
// search function
Node *del_node(Node *root, int id) {
int i;
if( root->Lid == id )
{ // 如果是要删除的节点
root->ID=-1;
for( i = 0; i < DICT_SIZE; i++ )
{
root->NSAB[i] = 0.0;//把布隆过滤器的值传递给节点的参数
root->uSAB[i] = 0.0;
}
root->Pl = NULL;
root->Pr = NULL;
root->Lid = -1;
}
else
{
del_node(root->Pl, id);
del_node(root->Pr, id);
}
root=root->Pf;
return root;
}
Node *update_index_tree(Node *root)
{
int i,j,k;
if (root != NULL)
{
for( j = 0; j < DICT_SIZE; j++ )
{
root->NSAB[j] = root->Pl->NSAB[j] + root->Pr->NSAB[j];//把NSAB和uSAB都作为树节点的一个参数
root->uSAB[j] = root->Pl->uSAB[j] + root->Pr->uSAB[j];
//此处应该把不同孩子的布隆过滤器直接相加,之后再把其中超过1的值变成1
if (root->NSAB[j]>1.0)
{
root->NSAB[j]=1.0;
}
if (root->uSAB[j]>1.0)
{
root->uSAB[j]=1.0;
}
}
if (root->Pf!=NULL)
{
root=root->Pf;
update_index_tree(root);
}
}
return root;
}
// write tree to file
void tree2file( FILE *fp, Node *root ) {
if( root == NULL ) return ;
int j,k;
// ID
fprintf(fp, "%d ", root->ID);
// NSAB
for( j = 0; j < DICT_SIZE; j++ ) {
fprintf(fp, "%lf ", root->NSAB[j]);
}
/* secure kNN encryption */
for( j = 0; j < DICT_SIZE; j++ ) {
if( Sk[j] == 0 ) {//依据论文中的规则进行加密
SAB[0][j] = root->uSAB[j];
SAB[1][j] = root->uSAB[j];
} else {
SAB[0][j] = 0.5*root->uSAB[j] + rand()/RAND_MAX;//rand()/RAND_MAX,产生0到1的随机数
SAB[1][j] = root->uSAB[j] - SAB[0][j];
}
}
for( j = 0; j < DICT_SIZE; j++ ) {
root->SAB[0][j] = 0;//初始化节点的参数
root->SAB[1][j] = 0;
for( k = 0; k < DICT_SIZE; k++ ) {
root->SAB[0][j] += M[0][j][k] * SAB[0][k];//生成加密的随机向量
root->SAB[1][j] += M[1][j][k] * SAB[1][k];//二者形成加密的布隆过滤器
}
}
/*************************/
// SAB
for( j = 0; j < DICT_SIZE; j++ ) {
fprintf(fp, "%lf ", root->SAB[0][j]);//把节点参数写入树文件(后续就不用存储参数uSAB了)
fprintf(fp, "%lf ", root->SAB[1][j]);//仅保留加密的两个随机向量
}
// pointer
if( root->Pl == NULL )
fprintf(fp, "-1 ");
else
fprintf(fp, "%d ", root->Pl->ID);
if( root->Pr == NULL )
fprintf(fp, "-1 ");
else
fprintf(fp, "%d ", root->Pr->ID);
if( root->Pf == NULL )
fprintf(fp, "-1 ");
else
fprintf(fp, "%d ", root->Pf->ID);
// Lid
fprintf(fp, "%d\n", root->Lid);
// recursive call
tree2file(fp, root->Pl);
tree2file(fp, root->Pr);
return ;
}
int main( void ) {
int i, j, k;
FILE *fp;
Node *root, *q;
Node *Root;
int id=5;
//srand( time(NULL) );
// generate encryption vector and save to file(仅运行一次即可)
//fp = fopen(Sk_PATH, "w");
//for( j = 0; j < DICT_SIZE; j++ ) {
//Sk[j] = rand()%2;
//fprintf(fp, "%d ", Sk[j]);
//}
//fclose(fp);
// read the encryption vector from the Sk.txt
fp = fopen(Sk_PATH, "r");
for( j = 0; j < DICT_SIZE; j++ ) {
fscanf(fp, "%d ", &Sk[j]);
}
// read Matrixs(指矩阵的转置) from file
fp = fopen(MATRIX_PATH, "r");
for( k = 0; k < 2; k++ ) {
for( i = 0; i < DICT_SIZE; i++ ) {
for( j = 0; j < DICT_SIZE; j++ ) {
fscanf(fp, "%lf ", &M[k][i][j]);
}
}
}
fclose(fp);
struct timeval starttime, endtime;
double t = 0; //计算时间
gettimeofday(&starttime, NULL);
// read tree from file
fp = fopen("./Updatetree500.txt", "r");//手动修改要搜索的树
root = file2tree(fp);
addparent(root,q);
fclose(fp);
puts("\n\n*** Finish reading the tree with father pointer from file. ***\n\n");
Root=update_index_tree(del_node(root, id));
puts("\n\n*** Finish update the index tree. ***\n\n");
// write tree to file
fp = fopen("UpdatedEtree500.txt", "w");//可以每次改文件名,EtreeX.txt
tree2file(fp, Root);
fclose(fp);
gettimeofday(&endtime, NULL);
t = 1000 * (endtime.tv_sec - starttime.tv_sec) + (endtime.tv_usec - starttime.tv_usec)/1000; //ms
printf("the times of search is:%d:%lf",FILE_SIZE,t);//显示搜索的规模和搜索时间
printf("ms\n");
return 0;
}