2015-08-04 1 views
0

У меня есть эти четыре файла,Крошечные ошибка связанного списка в C

tinyll.c tinyll.h в/главная/пользователя/Библиотека

test.c tinyll.h в/главная/пользователя/код

и скомпилируйте эту инструкцию для создания статической библиотеки libtinyll.a и используйте ее.

; in lib 
$ gcc -c tinyll.c 
$ ar -cvq libtinyll.a *.o 

; in code 
$ gcc -o test test.c ../lib/libtinyll.a 

До здесь все в порядке. Но я не знаю, почему я получаю ошибку сегментации, потому что работают строки из [CODE ERROR], но showElements. Цель - не передавать код от test.c до tinyll.c для обработки крошечного списка. Как это исправить?

/////////////////////////////////// test.c 

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#include "tinyll.h" 

int main(int argc, char *argv[]) 
{  
    progname = argv[0]; 

    char *file = "fwords"; 
    int n; 
    PTLL lsone = NULL; 
    n = loadfileinTLL(file,&lsone); 

    // work. good. 
    showElements(lsone); 

    // [CODE ERROR] 
    // Why here dont work? 
    // segmentation fault, load the first word 
    // but in the second crash. 
    while (lsone != NULL) { 
     printf("%s",lsone->word); 
     lsone = lsone->next; 
    }  
    return 0; 
} 

/////////////////////////////////// tinyll.c 

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#include "tinyll.h" 

void addElement(PPTLL lst, char data[]) 
{ 
    PTLL elemt; 
    elemt = (PTLL) malloc(sizeof(TLL)); 

    if (elemt == NULL) { 
     fprintf(stderr, "%s: insufficient memory.\n", progname); 
     exit(1);  
    } 

    if (*lst == NULL) 
    { 
     strncpy(elemt->word, data, 45); 
     elemt->next = NULL; 
     *lst = elemt; 
    } 
    else { 
     // add in front of list 
     strncpy(elemt->word, data, 45); 
     elemt->next = *lst; 
     *lst = elemt; 
    } 
} 

void showElements(PTLL lst) 
{ 
    while (lst != NULL) { 
     printf("%s\n",lst->word); 
     lst = lst->next; 
    } 
} 

int loadfileinTLL(char *filepath, PPTLL plst) 
{ 
    FILE *f; 
    if ((f = fopen(filepath, "r")) == NULL) { 
     fprintf(stderr, "%s: error to load file %s.\n", progname, filepath); 
     exit(1); 
    } 

    char buf[45]; int n=0; 
    while (fgets(buf,sizeof(buf),f) != NULL) { 
     char *nl; 
     if ((nl = strchr(buf,'\n')) != NULL) { 
      *nl = '\0'; 
     } 
     addElement(plst,buf); 
     n++; 
    } 

    fclose(f); 

    return n; 
} 

//////////////////////////////////// tinyll.h 

#include <stdio.h> 
#include <stdlib.h> 

#ifndef _TINYLL_ 
#define _TINYLL_ 

struct list { 
    char word[45]; 
    struct list *next; 
}; 

// Tiny Linked List 
typedef struct list TLL; 
typedef struct list *PTLL; 
typedef struct list **PPTLL; 
char *progname; 

#endif 
+1

Выполнить код в отладчике (например. 'Gdb'). Он должен прекратить работу программы. Затем вы можете получить место, где произошел сбой кода, используя команду backtrace ('bt') и проверить переменные с помощью' print (некоторое выражение) ' –

+0

Возможно, вы захотите использовать [include guard] (https://en.wikipedia.org/вики/Include_guard). – Jashaszun

+1

Вы хотите сделать другой указатель, чтобы уйти из связанного списка. Если вы используете свой дескриптор в связанном списке для перемещения (то есть: 'lsone'), тогда у вас будут утечки памяти –

ответ

0

следующий код:

1) compiles cleanly 
2) performs correctly, with out seg faulting. 
3) checks and handles errors correctly 
4) cleans up after itself, by freeing any allocated memory 
5) removed leading underscores from names 
    as leading underscores has special meaning to the compiler 

tinyll.h

#ifndef TINYLL_ 
#define TINYLL_ 

struct list 
{ 
    char word[45]; 
    struct list *next; 
}; 

// Tiny Linked List 
typedef struct list TLL; 
typedef struct list *PTLL; 
typedef struct list **PPTLL; 
extern char *progname; 

void addElement(PPTLL lst, char data[]); 
void showElements(PTLL lst); 
int loadfileinTLL(char *filepath, PPTLL plst); 


#endif // TINYLL_ 

tinyll.c

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#include "tinyll.h" 

void addElement(PPTLL lst, char data[]) 
{ 
    PTLL elemt; 
    elemt = (PTLL) malloc(sizeof(TLL)); 

    if (elemt == NULL) { 
     fprintf(stderr, "%s: insufficient memory.\n", progname); 
     exit(1); 
    } 

    if (*lst == NULL) 
    { 
     strncpy(elemt->word, data, 45); 
     elemt->next = NULL; 
     *lst = elemt; 
    } 
    else { 
     // add in front of list 
     strncpy(elemt->word, data, 45); 
     elemt->next = *lst; 
     *lst = elemt; 
    } 
} 

void showElements(PTLL lst) 
{ 
    while (lst != NULL) { 
     printf("%s\n",lst->word); 
     lst = lst->next; 
    } 
} 

int loadfileinTLL(char *filepath, PPTLL plst) 
{ 
    int n=0; 

    FILE *f; 
    if ((f = fopen(filepath, "r")) == NULL) 
    { 
     fprintf(stderr, "%s: error to load file %s.\n", progname, filepath); 
     n = -1; 
    } 

    else 
    { 
     char buf[45]; 

     while (fgets(buf,sizeof(buf),f) != NULL) 
     { 
      char *nl; 
      if ((nl = strchr(buf,'\n')) != NULL) 
      { 
       *nl = '\0'; 
      } 
      addElement(plst,buf); 
      n++; 
     } 

     fclose(f); 
    } // endif 

    return n; 
} 

test.c

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#include "tinyll.h" 

char *progname; 

int main(int argc, char *argv[]) 
{ 
    if(1 == argc) 
    { 
     progname = argv[0]; 
    } 
    else 
    { 
     printf("USAGE: %s\n", argv[0]); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, right number (0) of arguments on command line 

    char *file = "fwords"; 
    int n; 
    PTLL lsone = NULL; 
    PTLL lstwo = NULL; 

    n = loadfileinTLL(file,&lsone); 

    if(n > 0) 
    { 

     // work. good. 
     showElements(lsone); 

     // [CODE ERROR] 
     // Why here dont work? 
     // segmentation fault, load the first word 
     // but in the second crash. 
     lstwo = lsone; 
     while (lstwo) 
     { 
      printf("%s",lstwo->word); 
      lstwo = lstwo->next; 
     } 
    } // endif 

    while(lsone) 
    { 
     lstwo = lsone->next; 
     free(lsone); 
     lsone = lstwo; 
    } // end while 

    return 0; 
} 

Я использовал следующее для тестового файла:

one 
two 
three 
four 
five 
six 

и выход был:

six 
five 
four 
three 
two 
one 
sixfivefourthreetwoone 
+0

, если опубликованный код был скомпилирован с включенными предупреждениями (для gcc, при минимальном использовании: «-Wall -Wextra -pedantic») Затем многие/большинство ошибок в коде было бы обнаружено. в общем, всегда исправлять (не скрывать) все предупреждения. В конце концов, компилятор знает язык намного лучше, чем люди знают язык. – user3629249

+0

BTW: gcc имеет PIC и статические параметры, доступные для создания статических библиотек в качестве третьего шага. лучше всего скомпилировать в качестве первого шага, затем шаг 2 - либо создать библиотеку, либо файлы объектных объектов и библиотеки в исполняемый файл – user3629249

Смежные вопросы