我的C代码中的分割错误需要帮助

问题描述:

我一直在试图确定我的程序在哪里生成分割都无济于事。 我需要帮助指出哪些字符串操作或字符指针在运行时导致分段错误。该程序编译成功,但在运行时出现分段错误。我的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

采用手工调试方法;

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

编译它,那么你可以很容易地看到你采取分段故障

我不知道你正在使用的编译器,但这里是一个快速指导如何使用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,这样你就可以得到一个快速的想法在什么命令的种类可供选择。

最明显的问题,我看到的是可能导致分段错误是在下面的代码:

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

*包含窗口大小调整处理