【问题标题】:C #define causes Seg Fault?C#define 导致 Seg 错误?
【发布时间】:2011-07-01 07:52:13
【问题描述】:

这是我试图在 Red Hat 6 上工作的功能..

而且我对 C 的使用经验很少,尤其是使用 #define,所以我不确定这部分甚至试图做什么:SP->s_port = htons(SP->s_port);强>

#ifdef __linux
#define GET_SERVICE_BY_NAME(SP, SERVICE, PROTOCOL)                           \
   char            GSBN_servbuf[HOSTBUFFERLENGTH] = {0};                     \
   struct servent  GSBN_sp;                                                  \
   struct servent *GSBN_serv_result;                                         \
   int             GSBN_s = 0;                                               \
   GSBN_s = getservbyname_r(SERVICE,                                         \
                       PROTOCOL,                                             \
                       &GSBN_sp,                                             \
                       GSBN_servbuf,                                         \
                       sizeof(GSBN_servbuf),                                 \
                       &GSBN_serv_result);                                   \
   SP = GSBN_serv_result;                                                    \
   SP->s_port = htons(SP->s_port);                                           \
   if (SP && SOCKET_DEBUG) {                                                 \
      printf("%s GET_SERVICE_BY_NAME - Service: %s Port: %d Protocol: %s\n", \
             get_timestamp(), SP->s_name, SP->s_port, SP->s_proto);          \
       }                                                                         \
   if (SP == NULL) {                                                         \
      fprintf(stderr, "%s GET_SERVICE_BY_NAME - Service %s not found.\n",    \
              get_timestamp(), SERVICE);                                     \
   }
#else
#define GET_SERVICE_BY_NAME(SP, SERVICE, PROTOCOL)                           \
   char            GSBN_servbuf[HOSTBUFFERLENGTH] = {0};                     \
   struct servent  GSBN_serv_result;                                         \
   SP = getservbyname_r(SERVICE,                                             \
                       PROTOCOL,                                             \
                       &GSBN_serv_result,                                    \
                       GSBN_servbuf,                                         \
                       sizeof(GSBN_servbuf));                                \
   if (SP && SOCKET_DEBUG) {                                                 \
      printf("%s GET_SERVICE_BY_NAME - Service: %s Port: %d Protocol: %s\n", \
             get_timestamp(), SP->s_name, SP->s_port, SP->s_proto);          \
   }                                                                         \
   if (SP == NULL) {                                                         \
      fprintf(stderr, "%s GET_SERVICE_BY_NAME - Service %s not found.\n",    \
              get_timestamp(), SERVICE);                                     \
   }
#endif

这是我得到的错误:

根据 gdb,我在此函数调用中遇到了段错误:

GET_SERVICE_BY_NAME(sp, serv, prot);

这是 gdb 输出:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x456c6c90 (LWP 14645)]
0x420b1e69 in gi_get_port (serv=Unhandled dwarf expression opcode 0x9c
)
    at /home/user1/Common/src/socket.c:282
282           GET_SERVICE_BY_NAME(sp, serv, prot);
Current language:  auto; currently c

以下是函数的调用方式:

int gi_get_port (char *serv, char *prot)
/* obtain the port for the named service */
{
  int p, s;

  /* Data for resolving service name to a socket description. */
  struct servent *sp = NULL;

  GET_SERVICE_BY_NAME(sp, serv, prot);

  if (sp != NULL) {
    p = sp->s_port;
  } else {
    p = -1;
  };

  return p;
}

【问题讨论】:

  • htons = "Host TO Network Short":将短整数从主机字节顺序(Intel 上的 LSB)转换为服务结构的网络字节顺序 (MSB)。
  • 我认为 sp 是一个 struct servent*,因为它被声明为 struct servent *sp = NULL;
  • 究竟GET_SERVICE_BY_NAME是宏还是函数?我会把它当作一个宏来读,但如果它是一个函数,那么 jleedev 是对的,你需要在声明中指定参数类型,并且分配给 SP 的值不会被泄露出来。这真的正是你所拥有的吗?
  • @Rup:它必须是一个宏——它没有使用有效的函数语法
  • 为什么是这些宏而不是函数? :|

标签: c gcc compilation


【解决方案1】:

这就是你的代码在预处理器执行后的样子:

int gi_get_port (char *serv, char *prot)
/* obtain the port for the named service */
{
  int p, s;

  /* Data for resolving service name to a socket description. */
  struct servent *sp = NULL;

  char            GSBN_servbuf[HOSTBUFFERLENGTH] = {0};                     
   struct servent  GSBN_sp;                                                  
   struct servent *GSBN_serv_result;                                         
   int             GSBN_s = 0;                                               
   GSBN_s = getservbyname_r(serv,                                         
                       prot,                                             
                       &GSBN_sp,                                             
                       GSBN_servbuf,                                         
                       sizeof(GSBN_servbuf),                                 
                       &GSBN_serv_result);                                   
   sp = GSBN_serv_result;                                                    
   sp->s_port = htons(SP->s_port);                                           
   if (sp && SOCKET_DEBUG) {                                                 
      printf("%s GET_SERVICE_BY_NAME - Service: %s Port: %d Protocol: %s\n", 
             get_timestamp(), sp->s_name, sp->s_port, sp->s_proto);          
       }                                                                         
   if (sp == NULL) {                                                         
      fprintf(stderr, "%s GET_SERVICE_BY_NAME - Service %s not found.\n",    
              get_timestamp(), serv);                                     
   }

  if (sp != NULL) {
    p = sp->s_port;
  } else {
    p = -1;
  };

  return p;
}

如您所见,在对端口执行 htons() 之前,您应该检查“sp”是否为“NULL”。

【讨论】:

    【解决方案2】:

    您的 HOSTBUFFERLENGTH 有多长?

    编译并运行代码,如果将 HOSTBUFFERLENGTH 设置为 1,我可以生成类似的崩溃,但如果设置为 2000 则看起来它可以工作......

    如果服务名称名称无效(例如“akhaha”而不是“http”,则 GSBN_serv_result 为 NULL,SP 为 NULL,SP->s_port 也会导致崩溃......

    【讨论】:

    • 这里是hostbufferlength设置为#define HOSTBUFFERLENGTH 1024
    • 问题在于 SP 是无效服务名称的 NULL 指针...您需要检查 NULL。
    猜你喜欢
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 2010-11-23
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多