将redisContext传递给另一个函数时,libhiredis不起作用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将redisContext传递给另一个函数时,libhiredis不起作用相关的知识,希望对你有一定的参考价值。
我正在尝试将自己的包装函数写入libhiredis以在我的项目中使用,但是当我尝试将redis_context传递给另一个函数以从那里发出命令时。代码段错误并通过gdb报告:
GDB错误:
Program received signal SIGSEGV, Segmentation fault.
sdscatlen (s=0x0, t=0x555555757690, len=22) at sds.c:239
239 sds.c: No such file or directory.
(gdb) backtrace
#0 sdscatlen (s=0x0, t=0x555555757690, len=22) at sds.c:239
#1 0x00007ffff7bcd300 in __redisAppendCommand (c=0x7fffffffddd0, cmd=<optimized out>, len=<optimized out>) at hiredis.c:910
#2 0x00007ffff7bcd38c in redisvAppendCommand (c=0x7fffffffddd0, format=<optimized out>, ap=<optimized out>) at hiredis.c:942
#3 0x00007ffff7bcd579 in redisvCommand (c=0x7fffffffddd0, format=<optimized out>, ap=ap@entry=0x7fffffffdcc0) at hiredis.c:1003
#4 0x00007ffff7bcd634 in redisCommand (c=<optimized out>, format=<optimized out>) at hiredis.c:1012
#5 0x0000555555554b9e in getnow (redis_context=0x7fffffffddd0) at src/testRedis.c:18
#6 0x0000555555554c14 in main () at src/testRedis.c:49
这是代码:
RedisWrapper.h:
#ifndef REDIS_WRAPPER_H
#define REDIS_WRAPPER_H
int redis_wrapper_init(redisContext *redis_context, char *ip, int port);
int redis_wrapper_set(redisContext *redis_context, char *key, char *value);
int redis_wrapper_get(redisContext *redis_context, char *key, char *retrieved_value);
#endif
RedisWrapper.c:
#include <hiredis.h>
int redis_wrapper_init(redisContext *redis_context, char* ip, int port) {
redis_context = redisConnect(ip, port);
if (redis_context == NULL || redis_context->err) {
if (redis_context) {
fprintf(stderr, "cget: redis init error: %s\n", redis_context->errstr);
} else {
fprintf(stderr, "cget: can't allocate redis context\n");
}
return 1;
}
return 0;
}
int redis_wrapper_set(redisContext *redis_context, char *key, char *value) {
redisReply *reply = redisCommand(redis_context, "SET %s %s", key, value);
if(reply == NULL) {
fprintf(stderr, "cget: redis set error key: %s, val: %s\n", key, value);
fprintf(stderr, "cget: redis set error: %s\n", redis_context->errstr);
return 1;
}
freeReplyObject(reply);
return 0;
}
int redis_wrapper_get(redisContext *redis_context, char *key, char *retrieved_value) {
redisReply *reply = redisCommand(redis_context, "GET foo");
if(reply == NULL) {
fprintf(stderr, "cget: redis get error key: %s\n", key);
fprintf(stderr, "cget: redis get error: %s\n", redis_context->errstr);
return 1;
}
printf("GET: %s\n", reply->str);
retrieved_value = reply->str;
freeReplyObject(reply);
return 0;
}
MAIN.C
#include <stdio.h>
#include <string.h>
#include <hiredis.h>
#include "RedisWrapper.h"
void getnow(redisContext *redis_context) {
redisReply *reply = redisCommand(redis_context, "GET foo");
printf("GET foo: %s\n", reply->str);
freeReplyObject(reply);
}
int main() {
redisContext *redis_context;
redis_wrapper_init(redis_context, "127.0.0.1", 6379);
getnow(redis_context);
return 0;
}
我的编译命令:
gcc -Wall -g -o src/redisTest src/RedisWrapper.c `pkg-config --cflags hiredis` src/Main.c `pkg-config --libs hiredis`
更多细节:
# uname -a
Linux node1 4.13.0-21-generic #24-Ubuntu SMP Mon Dec 17 17:29:16 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
# locate libhiredis
/usr/lib/x86_64-linux-gnu/libhiredis.a
/usr/lib/x86_64-linux-gnu/libhiredis.so
/usr/lib/x86_64-linux-gnu/libhiredis.so.0.13
/usr/share/doc/libhiredis-dbg
/usr/share/doc/libhiredis-dev
/usr/share/doc/libhiredis0.13
/usr/share/doc/libhiredis-dbg/changelog.Debian.gz
/usr/share/doc/libhiredis-dbg/copyright
/usr/share/doc/libhiredis-dev/README.md.gz
/usr/share/doc/libhiredis-dev/changelog.Debian.gz
/usr/share/doc/libhiredis-dev/copyright
/usr/share/doc/libhiredis0.13/changelog.Debian.gz
/usr/share/doc/libhiredis0.13/copyright
/var/cache/apt/archives/libhiredis-dbg_0.13.3-2_amd64.deb
/var/cache/apt/archives/libhiredis0.13_0.13.3-2_amd64.deb
/var/lib/dpkg/info/libhiredis-dbg:amd64.list
/var/lib/dpkg/info/libhiredis-dbg:amd64.md5sums
/var/lib/dpkg/info/libhiredis-dev:amd64.list
/var/lib/dpkg/info/libhiredis-dev:amd64.md5sums
/var/lib/dpkg/info/libhiredis0.13:amd64.list
/var/lib/dpkg/info/libhiredis0.13:amd64.md5sums
/var/lib/dpkg/info/libhiredis0.13:amd64.shlibs
/var/lib/dpkg/info/libhiredis0.13:amd64.symbols
/var/lib/dpkg/info/libhiredis0.13:amd64.triggers
我发现奇怪的是,如果我在Main.c中完成所有操作而不使用包装文件,它就可以工作。这对我的项目没有用,我需要能够传递redis_context并让它工作。
答案
redis_context
中的redis_wrapper_init
应该通过引用(在C中通过指针)传递,以在调用此函数后保留赋值redis_context = redisConnect(ip, port);
的结果。如果没有这个,则将redisConnect返回的指针分配给局部变量,该函数在函数返回时被销毁。
所以定义应该是
int redis_wrapper_init(redisContext ** redis_context, char* ip, int port) {
*redis_context = redisConnect(ip, port);
if (*redis_context == NULL || (*redis_context)->err) {
if (*redis_context) {
fprintf(stderr, "cget: redis init error: %s\n", (*redis_context)->errstr);
}
...
}
}
在主要你得到redis_context
变量的地址,并将其传递给redis_wrapper_init
redisContext *redis_context = 0;
redis_wrapper_init(&redis_context, "127.0.0.1", 6379);
以上是关于将redisContext传递给另一个函数时,libhiredis不起作用的主要内容,如果未能解决你的问题,请参考以下文章