我想将序列化密钥从文件恢复到模块中的redis内存。
以下是代码:
int Unarchive_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc != 2) {
RedisModule_WrongArity(ctx);
} else {
RedisModuleString *keyName = argv[1];
long long unarchiedKeys = 0;
const char *filename = RedisModule_StringPtrLen(keyName, NULL);
FILE *f = fopen(filename, "r");
if (f != NULL && access(filename, F_OK) != -1) {
struct stat info;
if (stat(filename, &info) != 0) {
RedisModule_ReplyWithError(ctx, "Error during file read");
}
size_t valueSize = info.st_size * sizeof(char);
char *keyValue = RedisModule_Alloc(valueSize);
fread(&keyValue, (size_t) info.st_size, 1, f);
fclose(f);
RedisModule_ReplyWithCallReply(ctx, RedisModule_Call(ctx, "RESTORE", "slbc", keyName, 0, keyValue, "REPLACE"));
remove(filename);
unarchiedKeys++;
}
RedisModule_ReplyWithLongLong(ctx, unarchiedKeys);
}
return REDISMODULE_OK;
}
当我运行此命令时,我在执行行SIGSEGV (Segmentation fault)
RedisModule_ReplyWithCallReply(ctx, RedisModule_Call(ctx, "RESTORE", "slcc", keyName, 0, keyValue, "REPLACE"));
任何人都可以帮我解决这个问题吗?
提前致谢。
答案 0 :(得分:1)
Segfaults 通常是通过取消引用空指针引起的,而空指针通常指向不属于进程地址空间的地址。这是一个很好的选择,这类问题是你的问题。一般来说,在使用变量之前,您似乎已经做了很好的验证变量,但有一些值得注意的例外:
ctx
(除非argc
计数错误,或stat
!= 0)正在调用RedisModule_ReplyWithCallReply
。这应该
使用前请检查它是否为空。RedisModule_Call
的返回值,则无法检查
被称为另一个函数的参数。根据此 API documentation ,此函数为错误的回复类型返回NULL。 建议删除对RedisModule_Call
的嵌入式调用,以便在将其作为参数传递给RedisModule_ReplyWithCallReply()
之前测试它的返回值。
RedisModuleCallReply *reply = RedisModule_Call(ctx, "RESTORE", "slbc", keyName, 0, keyValue, valueSize, "REPLACE");
if(!reply)
{
// handle error;
}
else
{
RedisModule_ReplyWithCallReply(ctx, reply);
}
<强> 编辑: 强>
另一个想法,一句话:
fread(&keyValue, (size_t) info.st_size, 1, f);
^//not needed
应该是:
fread(keyValue, (size_t) info.st_size, 1, f);