2013-10-31 57 views
0

我目前首次學習C,並且需要創建一個鏈接列表。過去我一直沒有簡單的問題,但是功能抽象和指針傳遞似乎讓我感到困惑,因爲我無法完成這個任務。運行程序時,我一直收到分段錯誤。基本上我從2個獨立的文件讀取數據,然後填充列表。從那裏我做了其他的數據,但在這個階段它是無關緊要的,因爲我甚至無法從文件中加載數據。這些列表使用從主函數到各種函數傳遞的tm結構(& tm)進行控制。嘗試創建鏈接列表的分段錯誤

我一直在使用Valgrind和gdb來嘗試和診斷,但是對於調試來說是新的使它很難。經過兩天的試驗和錯誤,我覺得我缺少一些重要的東西。這裏是我的代碼和錯誤消息:

/* global type definitions */ 
typedef struct tm * tm_type_ptr; 
typedef struct stock_list * stock_list_ptr; 
typedef struct coin * coin_list_ptr; 
typedef struct tm { 
    coin_list_ptr coins; 
    stock_list_ptr stock; 
} tm_type; 

/*coin structs*/ 
enum coin_types { 
    FIVE_CENTS=5, 
    TEN_CENTS=10, 
    TWENTY_CENTS=20, 
    FIFTY_CENTS=50, 
    ONE_DOLLAR=100, 
TWO_DOLLARS=200 
}; 

struct coin { 
    enum coin_types denomination; 
    unsigned count; 
}; 

/* stock structs*/ 
struct stock_data 
{ 
    char ticket_name[TICKET_NAME_LEN+1]; 
    char ticket_type; 
    char ticket_zone[TICKET_ZONE_LEN+1]; 
    unsigned int ticket_price; 
    unsigned int stock_level; 
}; 

typedef struct stock_node 
{ 
    struct stock_data * data; 
    struct stock_node * next_node; 
} stock_node; 

struct stock_list 
{ 
    stock_node * head_stock; 
    unsigned int num_stock_items; 
}; 

然後填充結構我使用了以下功能:

BOOLEAN system_init(tm_type * tm) 
{ 

    tm->coins=malloc(sizeof(struct coin) * NUM_COINS); 
    tm->stock=malloc(sizeof(struct stock_list)); 
    tm->stock->head_stock = malloc(sizeof(stock_node)); 
    tm->stock->head_stock->data = malloc(sizeof (struct stock_data)); 
    tm->coins->count = 0; 
    tm->stock->num_stock_items =0; 
    if (tm == NULL) 
    { 
    return FALSE; 
    } 
    else 
    { 
    return TRUE; 
    } 
} 

BOOLEAN load_data(tm_type * tm, char * stockfile, char * coinsfile) 
{ 
    FILE *stock_fp = fopen(stockfile, "r"); 
    FILE *coins_fp = fopen(coinsfile, "r"); 
    char *input= NULL, *token = NULL; 
    unsigned coin_type, amount; 
    /*stock variables*/ 
    unsigned stock_count=0; 
    unsigned int ticket_price, stock_level; 

    char *ticket_name = NULL, ticket_type, *ticket_zone= NULL; 
    while(fgets(input, buffer_size, coins_fp) != NULL) 
    { 
     token= strtok(input, ","); 
     coin_type = strtol(token, NULL, 10); 
     if(token != NULL) 
     { 
      token= strtok(NULL, ","); 
      amount = strtol(token, NULL, 10); 
     } 

     if(!populate_coin_array(tm, coin_type, amount)) 
     { 
      printf("OMG YOU SUCK!\n"); 
     } 
    } 
    } 
    /*display_coin_array(tm); */ 
} 
fclose(coins_fp); 
free(input); 
/*read stock file and populate stock structure */ 
if(fseek(stock_fp ,0, SEEK_END) == 0) 
{ 
    long buffer_size = ftell(stock_fp); 
    if(buffer_size == -1) 
    { 
    printf("Error! Exiting!\n"); 
    return FALSE; 
    } 
    input = malloc(sizeof(char) * (buffer_size+1)); /*allocate buffer size plus one for  `  '\0'*/ 

    if(fseek(stock_fp,0,SEEK_SET) == 0) 
    { 
    while(fgets(input, buffer_size, stock_fp) != NULL) 
    { 
     ticket_name = strtok(input, ","); 
     ticket_type = *(strtok(NULL, ",")); 
     ticket_zone = strtok(NULL, ","); 
     token = strtok(NULL, ","); 
     ticket_price = strtol(token, NULL, 10); 
     token = strtok(NULL,","); 
     stock_level = strtol(token, NULL, 10); 
     stock_count++; 
     if(!populate_stock_list(tm, ticket_name, ticket_type, ticket_zone, 
     ticket_price, stock_level, stock_count)) 
     { 
      printf("ERROR!!!\n"); 
     } 

    }  

    } 
    display_stock_list(tm, stock_count); 
} 
fclose(stock_fp); 
free(input); 
return TRUE; 
} 

BOOLEAN populate_coin_array(tm_type *tm, unsigned coin_type, unsigned amount) 
{ 
    struct coin single_coin; 
    struct coin *coin_array; 
    coin_array = malloc(sizeof(struct coin) * NUM_COINS); 
    single_coin = *(tm->coins); 
    single_coin.denomination = coin_type; 
    single_coin.count = amount; 
    *coin_array = single_coin; 
    tm->coins = coin_array; 
    return TRUE; 
} 

BOOLEAN populate_stock_list(tm_type *tm, char *ticket_name, char ticket_type, 
char *ticket_zone, unsigned int ticket_price, unsigned int stock_level, 
unsigned int stock_count) 
{ 
    tm_type temp_list; 
    struct stock_node *new_node; 
    temp_list = *tm; 
    new_node = malloc(sizeof(stock_node*)); 
    if(new_node != NULL) 
    { 
     strcpy(new_node->data->ticket_name, ticket_name); 
     new_node->data->ticket_type = ticket_type; 
     strcpy(new_node->data->ticket_zone , ticket_zone); 
     new_node->data->ticket_price = ticket_price; 
     new_node->data->stock_level = stock_level; 
     new_node->next_node = temp_list.stock->head_stock; 
     temp_list.stock->head_stock = new_node; 
     temp_list.stock->num_stock_items = stock_count; 
    } 
    return TRUE; 
} 

我爲亂碼大量堆對不起,我已經拍攝它一些.c和.h文件。我儘可能減少修剪,以便更容易排除故障。

Valgrind是給我這個:

==16716== Use of uninitialised value of size 8 
==16716== at 0x4C2BFFC: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64- 
linux.so) 
==16716== by 0x400D37: populate_stock_list (tm_stock.c:37) 
==16716== by 0x40128F: load_data (tm_utility.c:129) 
==16716== by 0x40098F: main (tm.c:57) 
==16716== 
==16716== Invalid write of size 1 
==16716== at 0x4C2BFFC: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64- 
linux.so) 
==16716== by 0x400D37: populate_stock_list (tm_stock.c:37) 
==16716== by 0x40128F: load_data (tm_utility.c:129) 
==16716== by 0x40098F: main (tm.c:57) 
==16716== Address 0x0 is not stack'd, malloc'd or (recently) free'd 
==16716== 
==16716== 
==16716== Process terminating with default action of signal 11 (SIGSEGV) 
==16716== Access not within mapped region at address 0x0 
==16716== at 0x4C2BFFC: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64- 
linux.so) 
==16716== by 0x400D37: populate_stock_list (tm_stock.c:37) 
==16716== by 0x40128F: load_data (tm_utility.c:129) 
==16716== by 0x40098F: main (tm.c:57) 

能幫點我朝着正確的方向?我不希望任何人給我答案,我只想知道爲什麼會發生這種情況。

謝謝!

回答

1

在使用之前,您需要爲new_node->data分配struct stock_data *。 此外,在malloc()傳遞您爲其指針的大小分配的結構大小。

更新將

//--------------------------------v no * here 
new_node = malloc(sizeof(*new_node)); 
if(new_node != NULL) 
{ 
    new_node->data = malloc(sizeof(*(new_node->data))); 
    ... 
    //your code 
+0

感謝羅漢,原來如此!我正在摸索着想着去哪裏分配內存。我明白Valgrind也在寄給我,我只是覺得我沒有提前分配內存。再次感謝你,我真的很感激! – Lukaaaaaaaay

+0

我相信「sizeof pointer」是一個誤解......它應該是'new_node = malloc(sizeof * new_node);',它不需要輸出類型的名稱,並且「鎖定」分配大小爲實際表達式的大小,可以很容易地驗證它是否正確,即指針接收'malloc()'的返回值。 – unwind