无法从 c 中的不同函数从 GDBM 数据库中检索数据
Posted
技术标签:
【中文标题】无法从 c 中的不同函数从 GDBM 数据库中检索数据【英文标题】:Unable to retrive data from GDBM databas from differnt function in c 【发布时间】:2021-03-01 18:57:45 【问题描述】:您好,我正在尝试开发带有嵌入式数据库的 3 层服务器。
我的问题是我能够将数据保存在 gdbm 数据库中,但是当我尝试从其他函数检索数据时,它总是返回空值。 我还指出了一个问题,即在我保存数据时键值的空终止(通过 gdb 输出验证)不以 \0 结尾,但在检索数据时它以 \0 终止我不太确定这一点理论不知道怎么解决。
我尝试过的事情:
尝试手动添加空字符但没有成功 厌倦了从键中删除空字符,但它仍然不起作用。 试图从相同的结构中获取密钥,希望该问题可能是由于格式不同但没有奏效 尝试替换空字符但没有帮助,因为我不知道自己做错了什么以及为什么在保存数据时没有空字符。我附上了重现相同错误的最少代码,希望有人会指出我的错误,同时我仍会尝试解决此问题,但您的指南可能会有所帮助。
源代码
#include <gdbm.h>
#include <string.h>
#include <stdio.h>
#define STR_SIZE 20
#define BUFFER_SIZE 256
typedef struct UserData
char name[STR_SIZE];
char accountNumber[STR_SIZE];
char password[STR_SIZE];
long balence;
userData;
void simulateSelect(GDBM_FILE dbFile);
void simulateInsert(GDBM_FILE dbFile);
int main(int argc, char **argv)
GDBM_FILE dbFile = gdbm_open("newSampleDB", 0, GDBM_WRCREAT | GDBM_READER, 0660, 0);
simulateInsert(dbFile);
simulateSelect(dbFile);
return 0;
void simulateInsert(GDBM_FILE dbFile)
//RPC call data sent to server [function mode [data for function call]
char *request = "signup user fawad 10120 11223 120";
//server receiving end
char buffer[BUFFER_SIZE];
char name[STR_SIZE];
char id[STR_SIZE];
char pass[STR_SIZE];
char bal[STR_SIZE];
char temp[STR_SIZE];
char mode[STR_SIZE];
//parse cliet request and slect one of the avaiable opertaion
sscanf(request, "%s %s %s %s %s %s", temp, mode, name, id, pass, bal);
bzero(buffer, BUFFER_SIZE);
//forward request to database server
sprintf(buffer, "insert %s %s %s %s %s", mode, name, id, pass, bal);
// databse server receiving end
userData data;
bzero(name, STR_SIZE);
bzero(id, STR_SIZE);
bzero(pass, STR_SIZE);
//parse request and take actoin
sscanf(buffer, "%s %s %s %s %s %li", temp, temp, name, id, pass, &data.balence);
strcpy(data.name, name);
strcpy(data.accountNumber, id);
strcpy(data.password, pass);
//save data in database
datum key;
// i have checked through gdb at this point key.dptr does not have null termination i.e. \0
// key.dptr = 10120
key.dptr = data.accountNumber;
key.dsize = STR_SIZE + 1;
datum _data;
_data.dptr = (char *)&data;
_data.dsize = sizeof(data);
int res = gdbm_store(dbFile, key, _data, GDBM_INSERT);
printf("Indert Status = %d", res);
//works fine here and data is retrived
datum data3 = gdbm_fetch(dbFile, key);
userData *data1 = (userData *)(data3.dptr);
sprintf(buffer, "1 %s %s %s %li", data1->name, data1->accountNumber, data1->password, data1->balence);
fprintf(stdout, "%s", buffer);
void simulateSelect(GDBM_FILE dbFile)
//client again initiates request to login
char *request = "login user 10120 11223";
//server end
char buffer[BUFFER_SIZE];
char id[STR_SIZE];
char pass[STR_SIZE];
char temp[STR_SIZE];
char mode[STR_SIZE];
bzero(buffer, BUFFER_SIZE);
//parse request and select operatoin
sscanf(request, "%s %s %s %s", temp, mode, id, pass);
//send request to database server
sprintf(buffer, "select %s %s", mode, id);
//databse server end
bzero(id, STR_SIZE);
//parse request
sscanf(buffer, "%s %s %s", temp, mode, id);
// userData d;
// strcpy(d.accountNumber, id);
datum _data;
datum key;
// at this point key.dptr have null termiantion i.e key.dptr= 10120\0
key.dptr = id;
// key.dptr = d.accountNumber;
key.dsize = STR_SIZE + 1;
_data = gdbm_fetch(dbFile, key);
userData *data = (userData *)(_data.dptr);
// ((userData *)res.dptr)->name)
sprintf(buffer, "1 %s %s %s %li", data->name, data->accountNumber, data->password, data->balence);
fprintf(stdout, "%s", buffer);
【问题讨论】:
你有key.dsize = STR_SIZE + 1;
为什么+ 1
?
容纳空字符,以防密钥与STR_SIZE的长度相同,即20
但是空终止符应该在数组本身中。通过告诉 GDBM 密钥大小是 STR_SIZE + 1
您告诉它超出数组的范围,您将有未定义的行为。
当密钥长度为STR_SIZE
个字符时,该空字符存储在哪里?
感谢@Someprogrammerdude 指出,我现在会尝试,但我已经使用 bzero 函数将数组分配为零
【参考方案1】:
问题很可能是您使用accountNumber
数组的整个(以及更多!)作为键,甚至字符串空终止符之外的部分也将未初始化且具有不确定性价值观。
因此,您在写入时使用的密钥可能与您在读取数据时使用的密钥不完全相同。
解决方案是确保所有accountNumber
数组在将字符串复制到它之前都将被初始化(如memset(data.accountNumber, 0, sizeof data.accountNumber)
)。
例如的问题
bzero(id, STR_SIZE);
// ...
strcpy(data.accountNumber, id);
是strcpy
不会复制超出字符串空终止符的数据,所以它不会复制整个数组id
,只是复制其中的一小部分。这将使data.accountNumber
的其余元素未初始化。
您必须自己初始化data.accountNumber
。
【讨论】:
谢谢它解决了我正在考虑的问题,如果一个数组被初始化,那么下一个 strcpy 将自动从源获取所有数据。以上是关于无法从 c 中的不同函数从 GDBM 数据库中检索数据的主要内容,如果未能解决你的问题,请参考以下文章