c - 尝试创建链接列表时出现段错误

标签 c

我目前正在第一次学习 C,为了完成一项作业,我需要创建一个链接列表。我过去没有遇到过简单的问题,但是功能抽象和指针传递似乎让我感到困惑,因为我无法让这个继续下去。运行程序时我不断收到段错误。基本上我从两个单独的文件中读取数据,然后填充列表。从那里我对数据进行其他处理,但在这个阶段它是无关紧要的,因为我什至无法从文件中加载数据。这些列表使用 tm 结构进行控制,该结构从 main 传递(&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)

可以帮我指出正确的方向吗?我不指望任何人能给我答案,我只是想知道为什么会发生这种情况。

谢谢!

最佳答案

使用前需要分配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

关于c - 尝试创建链接列表时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19703060/

相关文章:

c - c中没有返回错误

c - 在链表前面插入一个节点

c - 在 C 中读取和写入字节(来自/在文件中)

C 循环-可以在循环内更改计数器或条件吗?

c - itoa 函数不适用于单位数整数

c++ - 字符串到字节数组

c - 设置孪生指针的最有效算法

c# - 在同一行读取 3 个变量 C#

c - 如何在流套接字字节流中查找特定字符串

c - 向二叉搜索树添加节点随机删除节点