【发布时间】:2015-09-24 14:38:19
【问题描述】:
my rpc_telnet.x is below,
01
02 struct rpc_telnet_data {
03 string user_id<50>;
04 };
05
06 struct rpc_result {
07 string msg<50>;
08
09 };
10
11 program RPC_TELNET_PROG {
12 version RPC_TELNET_VERS {
13 rpc_result RPC_TEST(rpc_telnet_data) = 1;
14
15 } = 1;
16 } = 0x23451112;
};
program RPC_TELNET_PROG {
version RPC_TELNET_VERS {
rpc_result RPC_TEST(rpc_telnet_data) = 1;
} = 1;
} = 0x23451112;
`
------------------------
当服务器端返回为整数时(我设置了整数版本 rpc_telnet.x ),它工作得很好。 但是当服务器端返回结果为字符串(char*)时,会出现段错误。 那么,如何正确设置 return char(result->msg) ? 下面是我的服务器端代码。
rpc_telnet_server.c
------------------------------------------------
01 /*
02 * This is sample code generated by rpcgen.
03 * These are only templates and you can use them
04 * as a guideline for developing your own functions.
05 */
06
07 #include "rpc_telnet.h"
08
09 bool_t
10 rpc_test_1_svc(rpc_telnet_data *argp, rpc_result *result, struct svc_req *rqstp)
11 {
12 bool_t retval=1;
13 cout << (*argp).user_id << endl;
14 result->msg = "kk";
15 /*
16 * insert server code here
17 */
18
19 return (retval);
20 }
21
22 int
23 rpc_telnet_prog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
24 {
25
26 (void) xdr_free(xdr_result, result);
27
28 /*
29 * Insert additional freeing code here, if needed
30 */
31
32 }
rpc_telnet_svc.c
------------------------------------------------
001 /*
002 * Please do not edit this file.
003 * It was generated using rpcgen.
004 */
005
006 #include "rpc_telnet.h"
007 #include <stdio.h>
008 #include <stdlib.h> /* getenv, exit */
009 #include <rpc/pmap_clnt.h> /* for pmap_unset */
010 #include <string.h> /* strcmp */
011 #include <rpc/rpc_com.h>
012 #include <fcntl.h> /* open */
013 #include <unistd.h> /* fork / setsid */
014 #include <sys/types.h>
015 #include <string.h>
016 #include <sys/resource.h> /* rlimit */
017 #include <syslog.h>
018
019 #ifdef DEBUG
020 #define RPC_SVC_FG
021 #endif
022
023 void
024 rpc_telnet_prog_1(struct svc_req *rqstp, SVCXPRT *transp)
025 {
026 union {
027 rpc_telnet_data rpc_test_1_arg;
028 } argument;
029 union {
030 rpc_result rpc_test_1_res;
031 } result;
032 bool_t retval;
033 xdrproc_t xdr_argument, xdr_result;
034 bool_t (*local)(char *, void *, struct svc_req *);
035
036 switch (rqstp->rq_proc) {
037 case NULLPROC:
038 (void) svc_sendreply(transp,
039 (xdrproc_t) xdr_void, (char *)NULL);
040 return;
041
042 case RPC_TEST:
043 xdr_argument = (xdrproc_t) xdr_rpc_telnet_data;
044 xdr_result = (xdrproc_t) xdr_rpc_result;
045 local = (bool_t (*) (char *, void *, struct svc_req *))rpc_test_1_svc;
046 break;
047
048 default:
049 svcerr_noproc(transp);
050 return;
051 }
052 (void) memset((char *)&argument, 0, sizeof (argument));
053 if (!svc_getargs(transp, xdr_argument, (char *)(caddr_t) &argument)) {
054 svcerr_decode(transp);
055 return;
056 }
057 retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp);
058
059
060
061 if (retval > 0 && !svc_sendreply(transp, xdr_result, (char *)&result)) {
062
063 svcerr_systemerr(transp);
064 }
065
066 if (!svc_freeargs(transp, xdr_argument, (char *)(caddr_t) &argument)) {
067 fprintf(stderr, "unable to free arguments");
068 exit(1);
069 }
070
075
076 if (!rpc_telnet_prog_1_freeresult(transp, xdr_result,(char *) (caddr_t) &result))
077 fprintf(stderr, "unable to free results");
078
079 cout << "rpc_telnet_prog_1_freeresult end" << endl;
080
081 return;
082 }
083
084 int
085 main()
086 {
087 pid_t pid;
088 int i;
089 #ifndef RPC_SVC_FG
090 int size;
091 struct rlimit rl;
092 pid = fork();
093 if (pid < 0) {
094 perror("cannot fork");
095 exit(1);
096 }
097 if (pid)
098 exit(0);
099 rl.rlim_max = 0;
100 getrlimit(RLIMIT_NOFILE, &rl);
101 if ((size = rl.rlim_max) == 0)
102 exit(1);
103 for (i = 0; i < size; i++)
104 (void) close(i);
105 i = open("/dev/console", 2);
106 (void) dup2(i, 1);
107 (void) dup2(i, 2);
108 setsid();
109 openlog("rpc_telnet", LOG_PID, LOG_DAEMON);
110 #endif
111 if (!svc_create(rpc_telnet_prog_1, RPC_TELNET_PROG, RPC_TELNET_VERS, "netpath")) {
112 fprintf(stderr, "unable to create (RPC_TELNET_PROG, RPC_TELNET_VERS) for netpath.");
113 exit(1);
114 }
115
116 svc_run();
117 fprintf(stderr, "svc_run returned");
118 exit(1);
119 /* NOTREACHED */
120 }
gdb ./rpc_telnet_server
---------------------
bt
01 [New LWP 100114]
02 [New Thread 28404300 (LWP 100114/rpc_telnet_server)]
03 55
04
05 Program received signal SIGSEGV, Segmentation fault.
06 [Switching to Thread 28404300 (LWP 100114/rpc_telnet_server)]
07 0x2822b584 in free () from /lib/libc.so.7
08 (gdb) bt
09 #0 0x2822b584 in free () from /lib/libc.so.7
10 #1 0x2824ad2a in xdr_string () from /lib/libc.so.7
11 #2 0x08048ec0 in xdr_rpc_result (xdrs=0x284821c8, objp=0xbfbfd514)
12 at rpc_telnet_xdr.c:21
13 #3 0x28238be3 in svc_create () from /lib/libc.so.7
14 #4 0x08048c4e in rpc_telnet_prog_1 (rqstp=0xbfbfd598, transp=0x28238be3)
15 at rpc_telnet_svc.c:71
16 #5 0x2823cfd8 in svc_getreq_common () from /lib/libc.so.7
17 #6 0x2823d541 in svc_getreqset () from /lib/libc.so.7
18 #7 0x281dbb64 in svc_run () from /lib/libc.so.7
19 #8 0x08048b3f in main () at rpc_telnet_svc.c:116
01 g++ -g -DRPC_SVC_FG -Wall -Wextra -pedantic -O2 -pipe -D_REENTRANT -D_THEAD_SAF -c rpc_telnet_clnt.c
02 g++ -g -DRPC_SVC_FG -Wall -Wextra -pedantic -O2 -pipe -D_REENTRANT -D_THEAD_SAF -c rpc_telnet_client.c
03 rpc_telnet_client.c: In function 'void rpc_telnet_prog_1(char*)':
04 rpc_telnet_client.c:18: warning: deprecated conversion from string constant to 'har*'
05 rpc_telnet_client.c:19: warning: deprecated conversion from string constant to 'har*'
06 g++ -g -DRPC_SVC_FG -Wall -Wextra -pedantic -O2 -pipe -D_REENTRANT -D_THEAD_SAF -c rpc_telnet_xdr.c
07 g++ -g -DRPC_SVC_FG -Wall -Wextra -pedantic -o rpc_telnet_client rpc_telnet_cln.o rpc_telnet_client.o rpc_telnet_xdr.o -pthread
08 g++ -g -DRPC_SVC_FG -Wall -Wextra -pedantic -O2 -pipe -D_REENTRANT -D_THEAD_SAF -c rpc_telnet_svc.c
09 rpc_telnet_svc.c: In function 'int main()':
10 rpc_telnet_svc.c:87: warning: unused variable 'pid'
11 rpc_telnet_svc.c:88: warning: unused variable 'i'
12 g++ -g -DRPC_SVC_FG -Wall -Wextra -pedantic -O2 -pipe -D_REENTRANT -D_THEAD_SAF -c rpc_telnet_server.c
13 rpc_telnet_server.c: In function 'bool_t rpc_test_1_svc(rpc_telnet_data*, rpc_reult*, svc_req*)':
14 rpc_telnet_server.c:14: warning: deprecated conversion from string constant to 'har*'
15 rpc_telnet_server.c: At global scope:
16 rpc_telnet_server.c:10: warning: unused parameter 'rqstp'
17 rpc_telnet_server.c:23: warning: unused parameter 'transp'
18 rpc_telnet_server.c: In function 'int rpc_telnet_prog_1_freeresult(SVCXPRT*, boo_t (*)(XDR*, ...), char*)':
19 rpc_telnet_server.c:32: warning: control reaches end of non-void function
20 g++ -g -DRPC_SVC_FG -Wall -Wextra -pedantic -o rpc_telnet_server rpc_telnet_svco rpc_telnet_server.o rpc_telnet_xdr.o -pthread
【问题讨论】:
-
我看到您在使用某些局部变量之前未能初始化它们。例如,
rpc_test_1_svc函数中的retval。未初始化的局部变量有一个indeterminate 值,使用它们(例如通过返回它)会导致未定义的行为。未定义的行为,无论它在哪里,都会使您的整个程序实际上无效。尝试在启用更多警告的情况下进行构建(例如,使用 GCC 或 Clang 构建时-Wall -Wextra -pedantic),并修复您收到警告的根本原因,因为警告通常表明您做了可疑或奇怪的事情。 -
此外,
rpc_telnet_prog_1_freeresult被声明为返回int,但根本不返回任何内容,这是 未定义行为 的另一种情况。如果这是您的实际代码,您需要修复这些问题,如果这不是您的实际代码,您需要明确告诉我们,以及代码中的哪些问题可以忽略。更好的是,不要显示不完整的代码,而是创建一个 Minimal, Complete, and Verifiable Example 并显示给我们。 -
关于你的调试器回溯,你能指出
rpc_telnet_svc.c中的第71行吗?否则我们很难找到它。 -
只是一个想法,你确定你可以为你的字符串使用任何指针吗?也许您应该尝试动态分配内存并将字符串复制到该内存中,并改用指向已分配内存的指针?
-
感谢您的建议,我重新编码并初始化
retval=1,使用 -Wall -Wextra -pedantic 编译。 rpc_telnet_svc.c 中的第 71 行是 svc_freeargs。 (第 061 行 svc_sendreply)似乎会将结果发送给客户端,此时我的客户端也会出现段错误。