2011-02-18 68 views
0

我一直在試圖確定我的程序在哪裏生成分割都無濟於事。 我需要幫助指出哪些字符串操作或字符指針在運行時導致分段錯誤。該程序編譯成功,但在運行時出現分段錯誤。我的C代碼中的分割錯誤需要幫助

#include<curses.h> 
#include<strings.h> 
#include<unistd.h> 
#include<stdlib.h> 

/*Implements a Scrolling headband that takes a string argument and continously scrolls*/    
int main(int argc, char* argv[]) 
{ 
    /*A Substring function to return substring of a string*/ 
    char *substr(const char *src, int start, int len); 
    /*Appends a character to the Given string*/ 
    void append(char* s, char c); 
    /***Check if the argument is invalid***/ 
    if(argc!=2) 
    { 
     puts("Invalid number of arguments: Usage:headband <String>"); 
    } 
    /**Get headtext from the string argument argv[1]**/ 
    char *headtext = argv[1]; 

    /*headband(headtext);*/ 
    /*temporary variable to store strings as execution progresses*/ 
    char temp[100]; 
    /*Counter for streaming and scolling headband text*/ 
    int count = 0; 
    /*Placeholder for temporary headband text*/ 
    char hold[100]; 
    int i; 
    /*maximum x and y co-ordinates of the Screen*/ 
    int max_x,max_y; 
    /*Initialize screen for ncurses*/ 
    initscr(); 
    /*Don't show cursor*/ 
    curs_set(0); 
    /*Get terminal console dimensions*/ 
    getmaxyx(stdscr, max_y, max_x); 
    /*Get console width set to default console screen width=80*/ 
    int consolewidth = max_x; 
    /*Clear the screen*/ 
    clear(); 
    /*Set the first value as end of String for the momment*/ 
    temp[0] = '\0'; 
    /*Run this loop continuously to keep scrolling*/ 
    for (;;) 
    { 
     for(i=0; i < strlen(headtext); i++) 
     { 
      count++; 
      /*Append headband text character by character to string hold*/ 
      append(temp, headtext[i]); 
      move(0,consolewidth - count); 
      if (consolewidth - count > 0) 
      { 
       mvaddstr(0,console_width-count,temp); 
       refresh(); 
      } 
      else if (consolewidth - count == 0) 
      { 
       strcpy(hold, temp); 
       char q; 
       int com = i; 
       for(;;) 
       { 
        /*Scroll text by triming one character at a time*/ 
        /*from the left, then adding that character to the*/ 
        /*right side of the text*/ 
        com = com + 1; 
        if (com < strlen(headtext)) 
        { 
         q = headtext[com]; 
        } 
        else 
        { 
         com = 0; 
         q = headtext[com]; 
         //q = hold[0]; 
        } 
        strcpy(hold, substr(hold, 1, strlen(hold) - 1)); 
        append(hold, q); 
        move(0,0); 
        clear(); 
        mvaddstr(0,0,hold); 
        refresh(); 
        usleep(50); 
       } 
      } 
      usleep(50); 
     } 
    } 
    return 0; 
} 

/*A Substring function to return substring of a string*/ 
char * substr(const char *src, int start, int len) 
{ 
    char *dest = malloc(len+1); 
    if (dest) 
    { 
     memcpy(dest, src+start, len);  
     dest[len] = '\0'; 
    } 
    return dest; 
} 

/*Appends a character to the Given string*/ 
void append(char s[], char c) 
{ 
    int len = strlen(s); 
    s[len] = c; 
    s[len+1] = '\0'; 
} 
+0

假設您處於Linux環境中,您必須使用GDB進行調試。它會停在發生崩潰的確切位置,所以你可以檢查變量值和幾乎所有你想要的東西。 – SirDarius 2011-02-18 12:10:52

+0

也許是調試器? – 2011-02-18 12:11:14

+0

可能不是問題,但您尚未終止第一條評論。如果混淆編譯器,則會發生任何事情。 – Dave 2011-02-18 12:12:22

回答

1

採用手工調試方法;

#define DEBUG(A) fprintf(stderr, "%d step\n", (A)) 
#define PRINT(A) fprintf(stderr, "%s\n", (A)) 

#include<curses.h> 
#include <strings.h> 
#include<unistd.h> 
#include<stdlib.h> 

int main(int argc, char* argv[]){ 

    char *substr(const char *src, int start, int len); 
    PRINT("at top of the main") ; /***/ 
    DEBUG(1); 
    void append(char* s, char c); 

    if(argc!=2) 
    { 
    puts("Invalid number of arguments: Usage:headband <String>"); 
    } 
    char *headtext = argv[1]; 
    DEBUG (2); 
    char temp[100]; 

    int count = 0; 

    char hold[100]; 
    int i; 

    int max_x,max_y; 

    initscr(); 
    DEBUG (3); 
    curs_set(0); 

    getmaxyx(stdscr, max_y, max_x); 
    DEBUG (4); 
    int consolewidth = max_x; 

    clear(); 
    DEBUG(5); 
    temp[0] = '\0'; 

    for (;;) 
    { 
    for(i=0; i < strlen(headtext); i++) 
    { 
     count++; 

     append(temp, headtext[i]); 
     DEBUG(6); 
     move(0,consolewidth - count); 
     DEBUG(7); 
     if (consolewidth - count > 0) 
     { 
     mvaddstr(0,console_width-count,temp); 
     refresh(); 
     } 
     else if (consolewidth - count == 0) 
     {     
     char q; 
     int com = i; 
     strcpy(hold, temp); 
     for(;;) 
     { 
      com = com + 1; 
      if (com < strlen(headtext)){ 
      q = headtext[com]; 
      DEBUG (10); 
      }else{ 
      com = 0; 
      q = headtext[com]; 
      //q = hold[0]; 
      } 
      strcpy(hold, substr(hold, 1, strlen(hold) - 1)); 
      append(hold, q); 
      move(0,0); 
      clear(); 
      mvaddstr(0,0,hold); 
      refresh(); 
      usleep(50); 
     } 
     } 
     usleep(50); 
    } 
    } 
    return 0; 
} 

char * 
    substr(const char *src, int start, int len) 
{ 
    char *dest = malloc(len+1); 
    PRINT ("in substr"); 
    if (dest) 
    { 
    memcpy(dest, src+start, len);  
    dest[len] = '\0'; 
    } 
    PRINT ("at the end of the sub); 
    return dest; 
} 

void append(char s[], char c) 
{  
    int len = strlen(s); 
    PRINT("in append function"); 
    s[len] = c; 
    s[len+1] = '\0'; 
    PRINT ("at the end of the append function"); 
} 

編譯它,那麼你可以很容易地看到你採取分段故障

1

我不知道你正在使用的編譯器,但這裏是一個快速指導如何使用GCC和GDB調試這:

$ gcc -g file.c -o myexec # the -g flag enables debug info 

$ gdb ./myexec 

現在你處於GDB提示符下。如果您需要設置命令行參數使用:

set args <arg1> <arg2> ... 

後運行程序

run 

一旦崩潰,你可以做各種各樣的事情。它還顯示程序中的哪一點發生了錯誤。你可能想使用這些命令:

bt   # prints the backtrace/call stack 
print <expr> # print value of an expression 

有一對夫婦的cheat sheets on the web,這樣你就可以得到一個快速的想法在什麼命令的種類可供選擇。

0

最明顯的問題,我看到的是可能導致分段錯誤是在下面的代碼:

if(argc!=2) 
{ 
    puts("Invalid number of arguments: Usage:headband <String>"); 
} 
char *headtext = argv[1]; 

識別已提供的參數無效號碼後,您繼續分配指針argv[1] 。如果用戶沒有提供您的參數,則結果是將NULL傳遞給strlen()。這會導致未定義的行爲,並且在Linux \ Unix上通常會崩潰。在我的簡短測試中,提供了一個參數確實導致滾動頭帶沒有任何崩潰。

你可能會考慮改變你的代碼,類似下面的東西:

if(argc<2) 
{ 
    puts("Invalid number of arguments: Usage:headband <String>"); 
    exit(EXIT_FAILURE); 
} 
char *headtext = argv[1]; 

更新
看來你當前的代碼是不必要的複雜性(例如,嵌套的無限循環)爲我所相信的是它的預期目的。目前形式的代碼還有幾個問題需要解決。有一個memory leak來自substr()函數中調用malloc(),並隨後丟失指向分配的內存的指針。如果用戶提供的文本大於您的temp[100]緩衝區的大小,則會使您的append()函數中的緩衝區溢出。由於長度不會改變,因此不必多次計算headtext的長度。

我認爲,詛咒應在raw terminal escape codes使用。 curses庫實際上是原始終端代碼的一個包裝,並提供了一個靈活且高效的API,因此應用程序不需要擔心底層終端的功能。也許NCURSES Programming HOWTOX/Open Curses, Reference Pages可能有一定用處。

我也不詛咒專家自己,但是,下面的例子顯示了鬆散的基礎上原來代碼中的另一個基於光標的方法,並似乎有相同的輸出*

#include<curses.h> 
#include<signal.h> 
#include<stdlib.h> 
#include<string.h> 
#include<unistd.h> 

/* maximum x and y co-ordinates of the window */ 
int max_x, max_y; 
/* pointer to headband buffer */ 
char * headband = NULL; 
/* counter for streaming and scolling headband text */ 
unsigned int count; 

/* Handler for window resize */ 
void handle_winch(int sig) 
{ 
    /* Function for initializing curses & headband buffer */ 
    void my_init(); 

    /* Disable signal handler during reinitialization */ 
    signal(SIGWINCH, SIG_IGN); 

    /* Reinitialize the window to update data structures */ 
    endwin(); 
    my_init(); 
} 

/* Function for initializing curses & headband buffer */ 
void my_init() 
{ 
    /* Initialize/Reinitialize screen for ncurses */ 
    initscr(); 
    curs_set(0); 
    clear(); 
    refresh(); 
    getmaxyx(stdscr, max_y, max_x); 

    /* Allocate/Reallocate and initialize scrolling headband buffer */ 
    free(headband); 
    headband = (char *)malloc(max_x+1); 
    memset(headband, ' ', max_x); 
    headband[max_x] = '\0'; 
    count = 0; 

    /* Setup signal handler for window resizing */ 
    signal(SIGWINCH, handle_winch); 
} 

/* Implements a scrolling headband that takes a 
* string argument and scrolls continously */ 

int main(int argc, char* argv[]) 
{ 
    char * headtext; 
    int headtext_len; 
    int size; 

    if(argc<2) 
    { 
     puts("Invalid number of arguments: Usage:headband <String>"); 
     exit(EXIT_FAILURE); 
    } 
    /* Get headtext from the argument argv[1] and compute length */ 
    headtext = argv[1]; 
    headtext_len = strlen(headtext); 

    /* Call common initialization/reinitialization routine */ 
    my_init(); 

    /* Run this loop continuously to keep scrolling */ 
    for(;;) 
    { 
     /* Store & use copy of max_x in case original max_x is 
     * modified in signal handler by window resize event */ 
     size = max_x; 

     /* Rotate headband by shifting entire buffer and then 
     * appending next character from headtext buffer */ 
     memmove(&headband[0], &headband[1], size-1); 
     headband[size-1] = headtext[count++ % headtext_len]; 

     /* Update window */ 
     move(0,0); 
     mvaddstr(0,0,headband); 
     refresh(); 
     usleep(50000); 
    } 

    /* Unreachable, but included for completeness */ 
    endwin(); 
    free(headband); 
    exit(EXIT_SUCCESS); 
} 

*包含窗口大小調整處理