C语言 Redis 模块恢复命令调用



我想将序列化密钥从文件还原到模块中的 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;
}

当我运行此命令时,我在执行第RedisModule_ReplyWithCallReply(ctx, RedisModule_Call(ctx, "RESTORE", "slcc", keyName, 0, keyValue, "REPLACE"));行时出现SIGSEGV (Segmentation fault)

谁能帮我解决这个问题?

提前谢谢。

隔离错误通常是由取消引用空指针引起的,而空指针通常指向不属于进程地址空间的地址。 可以肯定的是,这种事情是你的问题。 一般来说,在使用变量之前,您似乎已经很好地验证了变量,但有一些值得注意的例外:

  • 第一次使用ctx(除非计数错误argcstat!= 0( 在调用RedisModule_ReplyWithCallReply中。它应该 使用前检查它是否为空。
  • RedisModule_Call的返回值在 作为另一个函数的参数调用。 根据此API 文档,此函数为错误的回复类型返回 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);