2011-06-24 67 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