2011-06-24 36 views
0

我试图找到在C.解析例行的错误代码是:指针魔术有时会导致SIGSEGV

#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在另一个?

+0

让我们看看整个代码。可能你会修改'next'指针。我们希望看到这一点。 – mattn

+0

正如你写的那样,'next = strchr(“startstring”,'')'的结果是'NULL'。所以它不应该进入循环。 – IanNorton

+3

您正在写入一个常量字符串。 – Anycorn

回答

4

你不应该修改一个常量字符串,在这个例子中是"startstring"。我认为正常的应用程序工作,因为在那里使用的字符缓冲区是可变的。

+2

如果你想要一个可变数组中的字符串,使用'char cur [] =“startstring”;' – caf

+0

感谢junjanes和咖啡馆 - 问题出在我的主要方法。切换到'char time [] =“Thu Jun 16 04:53:00 +0000 2011”; getTime(time);'做了诀窍。 – Nils