2016-06-01 1 views
-2

code review에 내 코드를 올렸으며 오류 확인이 필요 없다는 답을 얻었습니다. 가끔 할C로 어썰트 및 오류 검사

  • 전제 조건에 대한 어설 및 사후
  • perror 사용 또는 유사한을,하지만 난 아직
  • 매뉴얼, 수작업으로 코딩 오류 - 그것을 배울하지 않았다 : AFAIK 나는 여러 가지 방법으로 오류 검사를 수행 할 수 있습니다 함수 또는 유사 항목의 부울 반환 값을 사용하여 호출이 성공 또는 실패했음을 나타냅니다.

더 많은 방법 또는 권장되는 특정 방법이 있습니까? perror과 단정을 모두 사용하는 것이 더 낫지 않습니까? 코드는 my github에 있으며 main 루프는 다음과 같습니다

int main(int argc, char *argv[]) { 
    bool donotrun = false; 
    struct sigaction new_action, old_action; 
    hashtable_t *hashtable = ht_create(65536); 
    /* Set up the structure to specify the new action. */ 
    new_action.sa_handler = termination_handler; 
    sigemptyset(&new_action.sa_mask); 
    new_action.sa_flags = 0; 

    sigaction(SIGINT, NULL, &old_action); 
    if (old_action.sa_handler != SIG_IGN) 
     sigaction(SIGINT, &new_action, NULL); 
    sigaction(SIGHUP, NULL, &old_action); 
    if (old_action.sa_handler != SIG_IGN) 
     sigaction(SIGHUP, &new_action, NULL); 
    sigaction(SIGTERM, NULL, &old_action); 
    if (old_action.sa_handler != SIG_IGN) 
     sigaction(SIGTERM, &new_action, NULL); 


    void *pParser; 
    char *c; 


    int index = 0; 
    int i; 
    char *cvalue = NULL; 
    const char *commandFile = ""; 
    bool quietFlag; 

    while (1) { 
     index = 0; 
     i = getopt_long(argc, argv, "pc:vh", 
         options, &index); 
     if (i == -1) 
      break; 
     switch (i) { 
      case 'p': { 
       exit(EXIT_SUCCESS); 
      } 
      case 'v': { 
       printf("sh OpenShell version 0.1(a)\n"); 
       printf("Version: %s\n", VERSION); 
       exit(EXIT_SUCCESS); 

      } 
      case 'h': { 
       usage(); 
       exit(EXIT_SUCCESS); 

      } 
      case 'c': { 
       cvalue = optarg; 
       command(cvalue, hashtable); 
       exit(EXIT_SUCCESS); 
      } 

      case 'f': 
       /* 
       * Execute commands from file. 
       * This is used for osh script files. 
       * The quiet flag is also set. 
       */ 
       if ((argc != 1) || commandFile) 
        usage(); 

       quietFlag = true; 
       argc--; 

       break; 


      case '?': 
       if (optopt == 'c') 
        fprintf(stderr, "Option -%c requires an argument.\n", optopt); 
       else if (isprint (optopt)) 
        fprintf(stderr, "Unknown option `-%c'.\n", optopt); 
       else 
        fprintf(stderr, 
          "Unknown option character `\\x%x'.\n", 
          optopt); 
      default: { 
       return 1; 
      } 
     } 
    } 
    getPath(); 
    pParser = (void *) ParseAlloc(malloc); 
    char *copy = ""; 

    for (; ;) { 
     bool scanning = true; 
     bool calc = true; 
     while (scanning) { 
      char *line = NULL; 
      line = readline("$ "); 
      if (line == NULL) { 
       /* No more lines, so exit the loop. */ 
       break; 
      } 
      if (line) 
       copy = strdup(line); 

      if (line && !strstr(line, "for") && !strstr(line, "==") && !strstr(line, "if") && strstr(line, "=")) { 
       donotrun = true; 
       char str[128]; 
       char *ptr; 
       strcpy(str, line); 
       strtok_r (str, "=", &ptr); 
       ht_set(hashtable, str, ptr); 
      } 

      if (!scanning) 
       break; 

      if (!isatty(fileno(stdin))) { 
       *argv++; 
       readFile(*argv++, hashtable); 
       free(line); 
       exit(0); 
      } 
      else { 

       if (!donotrun) { 
        line = str_replace(line, " | ", "|"); 
        line = str_replace(line, " |", "|"); 

        command(line, hashtable); 
       } 
       donotrun = false; 
       add_history(copy); 

      } 
      free(copy); 
     } 
    } 
    // ParseFree(pParser, free);FIXME: where should this go? 
    return 0; 
} 

그럼 내가 개발하는 동안 주석했다 주장을했고 지금은 주장 될해야하는지 모르겠어요.

/* Returns a struct that has the number of "chunks" the list of chunks. 
* Splits the command by char | and then by whitespace and return a list of struct pointers 
*/ 
struct str_list *list_split(const char *a_str, char *a_delim) { 

    char **result = 0; 
    size_t count = 0; 
    char *tmp = (char *) a_str; 
    char *ctmp; 
    char *token = ""; 
    char *last_comma = 0; 
    char *tmp2 = (char *) a_str; /* TODO: This variable can reuse tmp */ 
    //char *delim[2]; 
    //delim[0] = a_delim; 
    struct str_list *chunks = NULL; 
    /* Count how many elements will be extracted. */ 
    while (*tmp) { 
     if (*a_delim == *tmp) { 
      count++; 
      last_comma = tmp; 
     } 
     tmp++; 
    } 
    /* Add space for trailing token. */ 
    count += last_comma < (a_str + strlen(a_str) - 1); 
    count++; 
    result = alloc_argv(count); 
    char **tmpresult = alloc_argv(count); 
    chunks = malloc(count * sizeof *chunks); 
    if (result == NULL) { 
     printf("Error allocating memory!\n"); 
     return chunks;; 
    } 
    if (result) { 
     size_t idx = 0; 
     token = strtok((char *) strdup(a_str), "|"); 
     int a = 0; 
     while (token) { 
//   assert(idx < count); Why must I turn off assertions? 
      tmpresult[a] = strdup(token); 
      a++; 
      ctmp = strdup(token); 
      *(result + idx++) = ctmp; /* memory leak! how to free() */; 
      token = strtok(0, a_delim); 
     } 
//  assert(idx == count - 1); 
     *(result + idx) = 0; 
    } 
    chunks->argv = alloc_argv(BUFFER_SIZE);//malloc(chunks->size * sizeof(char *) * 1); 
    int i = 0; 
    chunks = tokenize(&i, chunks, result, count, tmp2); 
    chunks->pipes = i; /* important! to get this right */ 
    free(ctmp); 
    return expand_shell(tmpresult, chunks); 
} 
+0

잠깐, * 사용하고있는 것들에 대한 오류를 확인 하시겠습니까? 아니면 오류 방출을 구현하고 자신이 개발 한 것들을 확인 하시겠습니까? –

+0

@ MarcusMüller 왜 내가 내 주장을 주석으로 처리해야하는지 궁금해하며 필자가 작성한 코드에서 어설 션을 사용해야하는 곳이 궁금합니다. 어떤 곳에서는 이미'perror'를 사용하지만 자세한 내용은 알지 못합니다. –

+0

'perror()'는 에러를 검사하지 않습니다. 'errno'의 현재 값에 대한 긴 텍스트 오류 메시지를'stderr'에 기록합니다. – alk

답변

4

내가 아는 한, 단정은 개발 및 테스트 중에 만 사용해야합니다. assert는 실제로 매크로입니다. 디버그 구성으로 빌드하면 검사를 수행하고 false이면 종료합니다. 릴리스 구성에있을 때 아무 것도 수행하지 않습니다. 따라서 assert는 프로그래밍 오류를 검사하는 데 사용해야합니다.

http://www.cplusplus.com/reference/cassert/assert/

당신이 어설 함께 할 수 없어 인해 환경 또는 사용자 입력, 예를 들어,에 프로그램 실행 중에 발생 오류를 의미 런타임 오류를 확인하는 것입니다 프로그램은 파일을 열거 나 쓸 수 없으며 숫자가 예상 될 때 문자열을 입력하고 네트워크 연결을 설정할 수 없습니다. 이러한 검사는 디버그 모드와 릴리스 모드에서 모두 수행되기를 원합니다.

필자가 언급 한 두 가지 오류 검사 방법 인 perror와 반환 값 확인은 항상 함께한다고 생각합니다. 일반적으로 함수의 반환 값을 검사 한 다음 perror 또는 기타 함수를 사용하여 메시지를 인쇄 한 다음 오류 복구를 수행하거나 종료합니다. perror 자체는 단지 메시지를 출력하고 프로그램은 여러분이 다른 것을하지 않는 한 계속됩니다.

http://www.cplusplus.com/reference/cstdio/perror/

는 일반적으로 하나의 외부 함수 호출의 반환 값을 확인하고, 또한 정확성을위한 프로그램으로 모든 입력을 확인해야합니다. 대부분의 라이브러리 함수는 malloc 또는 printf를 포함하여 실패 할 수 있지만, 편집증 수준에 따라 응용 프로그램에 따라 문제 (파일, 네트워크, 라이브러리 또는 장치 초기화 등)를 일으킬 가능성이 가장 큰 라이브러리 만 검사하면 충분합니다.