指针魔术有时会导致SIGSEGV

时间:2011-06-24 06:16:14

标签: c pointers sigsegv

我试图在C中的解析例程中发现错误。代码是:

  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <time.h>
  #include <sys/time.h>

  static const char * month_abb_names[] =
  {
      "Jan",
      "Feb",
      "Mar",
      "Apr",
      "May",
      "Jun",
      "Jul",
      "Aug",
      "Sep",
      "Oct",
      "Nov",
      "Dec"
  };

  static const char * wday_abb_names[] =
  {
      "Mon",
      "Tue",
      "Wed",
      "Thu",
      "Fri",
      "Sat",
      "Sun",
  };

  time_t mb_mktime(char * time_str)
  {
      struct tm msg_time;
      char * cur, * next, *tmp_cur, *tmp_next, oldval;
      int counter = 0, tmp_counter = 0, i;
      int cur_timezone = 0, sign = 1;
      time_t retval;

      msg_time.tm_isdst = 0;
      cur = time_str;
      next = strchr(cur, ' ');
      while(next)
      {

          oldval = (*next);
          (*next) = '\0';
          switch(counter)
          {
          case 0 :
  // day of week
              for(i = 0; i < 7; i++)
              {
                  if(strncasecmp(cur, wday_abb_names[i], 3) == 0)
                  {
                      msg_time.tm_wday = i +1;
                      break;
                  }
              }
              break;
          case 1 :
  //month name
              for(i = 0; i < 12; i++)
              {
                  if(strncasecmp(cur, month_abb_names[i], 3) == 0)
                  {
                      msg_time.tm_mon = i;
                      break;
                  }
              }
              break;
          case 2 :
  // day of month
              msg_time.tm_mday = strtoul(cur, NULL, 10);
              break;
          case 3 :
  // HH:MM:SS
              tmp_cur = cur;
              tmp_next = strchr(cur, ':');
              tmp_counter = 0;
              while(tmp_next)
              {
                  switch(tmp_counter)
                  {
                  case 0 :
                      msg_time.tm_hour = strtoul(tmp_cur, NULL, 10);
                      break;
                  case 1 :
                      msg_time.tm_min = strtoul(tmp_cur, NULL, 10);
                      break;

                  }
                  tmp_cur = tmp_next + 1;
                  tmp_next =strchr(tmp_cur, ':');
                  tmp_counter++;
              }
              msg_time.tm_sec = strtoul(tmp_cur, NULL, 10);
              break;
          case 4 :
  // timezone
              if( (*cur) == '+')
              {
                  cur++;
              }
              else if ( (*cur) == '-')
              {
                  sign = -1;
                  cur++;
              }
              cur_timezone = (int)strtol(cur, NULL, 10);
              cur_timezone = sign * (cur_timezone / 100) * 60 * 60 + (cur_timezone % 100) * 60;
              break;
          }
          (*next) = oldval;
          cur = next + 1;
          next = strchr(cur, ' ');
          counter++;
      }
  // what's left is year
      msg_time.tm_year = strtoul(cur, NULL, 10) - 1900;

  #ifndef __WIN32
      retval = timegm(&msg_time) - cur_timezone;
  #else
      retval = mktime(&msg_time) - cur_timezone; // + some adjustments....
  #endif
      printf("final msg_time = %ld\n", retval);
      return retval;
  }

  void getTime(char * time_str)
  {
      time_t time = mb_mktime(time_str);
      struct tm  *ts;
      char buf[80];

      /* Format and print the time, "ddd yyyy-mm-dd hh:mm:ss zzz" */
      ts = localtime(&time);
      strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", ts);
      printf("%s --> %s\n", time_str, buf);
  }

  int main()
  {
      getTime("Thu Jun 16 04:53:00 +0000 2011");

      printf("done.");
      return 0;
  }

maingetTime是新的,mb_mktime只是略有修改

但是,行((*next) = '\0';)会产生SIGSEGV。我承认我很不确定为什么代码看起来像这样......

然而,代码在普通应用程序中运行良好。

有人可以解释为什么这个代码在一个应用程序中工作而SIGSEGV在另一个应用程序中工作?

1 个答案:

答案 0 :(得分:4)

您不应该修改常量字符串文字,在此示例中为"startstring"。我认为正常的应用程序是有效的,因为那里使用的char缓冲区是可变的。