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)
能幫點我朝着正確的方向?我不希望任何人給我答案,我只想知道爲什麼會發生這種情況。
謝謝!
感謝羅漢,原來如此!我正在摸索着想着去哪裏分配內存。我明白Valgrind也在寄給我,我只是覺得我沒有提前分配內存。再次感謝你,我真的很感激! – Lukaaaaaaaay
我相信「sizeof pointer」是一個誤解......它應該是'new_node = malloc(sizeof * new_node);',它不需要輸出類型的名稱,並且「鎖定」分配大小爲實際表達式的大小,可以很容易地驗證它是否正確,即指針接收'malloc()'的返回值。 – unwind