开发者

Pointer magic sometimes results in SIGSEGV

I am trying to find an error in a parsing-routine in C. The code is:

  #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;
  }

The main and getTime are new, the mb_mktime is only slightly modified from the original

However, the line ((*next) = '\0';) results in a SIGSEGV. 开发者_如何学JAVAI admit I am fairly uncertain why the code looks like this...

The code however works fine in the normal app.

Can someone explain why this code works in one app and SIGSEGVs in another?


You should not be modifying a constant string literal, which is "startstring" in this example. I suppose the normal app works because char buffers which are used there are mutable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜