0

我有奇怪的问题printf释放内存分配方面遇到了奇怪的问题。(因为你们总是要求我发布完整的代码。希望你不介意它的长度。)

我正在将其写入启动代码。所以我不允许更改结构或函数。

ievoid system_free(tm_type_ptr tm)是给我的,不允许更改它。

csv 文件在最后发布。现在问题:

1) A printfin afor loop打印结构元素的值。打印出正确的值。在第一个副本printf之后放置的副本给我带来了混乱的值。

printfs 在purchase_ticket()

我得到的输出是:

第一的printf

  5 = 10
 10 =  5
 20 =  8
 50 =  2
100 = 20
200 =  8

第二printf

  5 = 10
 10 =  5
 20 =  8
 50 =  2
100 = 20
200 = 56

这个输出是我能得到的最好的。这里只有200s 值不同。有时我也会得到 32232 种值。

2) system_free() 给我以下错误。可能我不知道如何释放内存或在何处/何时释放。

*** glibc detected *** ./tm: double free or corruption (out): 0x00007fff812582b0 ***
======= Backtrace: =========
/lib64/libc.so.6[0x38816760e6]
/lib64/libc.so.6[0x3881678c13]
./tm[0x4018e6]
./tm[0x400bde]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x388161ecdd]
./tm[0x400a29]
======= Memory map: ========
00400000-00403000 r-xp 00000000 fd:01 264655                             /home/assignment/tm
00602000-00603000 rw-p 00002000 fd:01 264655                             /home/assignment/tm
011f7000-01218000 rw-p 00000000 00:00 0                                  [heap]
3471200000-3471216000 r-xp 00000000 fd:00 131168                         /lib64/libgcc_s-4.4.7-20120601.so.1
3471216000-3471415000 ---p 00016000 fd:00 131168                         /lib64/libgcc_s-4.4.7-20120601.so.1
3471415000-3471416000 rw-p 00015000 fd:00 131168                         /lib64/libgcc_s-4.4.7-20120601.so.1
3880e00000-3880e20000 r-xp 00000000 fd:00 136224                         /lib64/ld-2.12.so
388101f000-3881020000 r--p 0001f000 fd:00 136224                         /lib64/ld-2.12.so
3881020000-3881021000 rw-p 00020000 fd:00 136224                         /lib64/ld-2.12.so
3881021000-3881022000 rw-p 00000000 00:00 0
3881600000-388178a000 r-xp 00000000 fd:00 136225                         /lib64/libc-2.12.so
388178a000-3881989000 ---p 0018a000 fd:00 136225                         /lib64/libc-2.12.so
3881989000-388198d000 r--p 00189000 fd:00 136225                         /lib64/libc-2.12.so
388198d000-388198e000 rw-p 0018d000 fd:00 136225                         /lib64/libc-2.12.so
388198e000-3881993000 rw-p 00000000 00:00 0
3881e00000-3881e83000 r-xp 00000000 fd:00 136235                         /lib64/libm-2.12.so
3881e83000-3882082000 ---p 00083000 fd:00 136235                         /lib64/libm-2.12.so
3882082000-3882083000 r--p 00082000 fd:00 136235                         /lib64/libm-2.12.so
3882083000-3882084000 rw-p 00083000 fd:00 136235                         /lib64/libm-2.12.so
7fa7870b9000-7fa7870bc000 rw-p 00000000 00:00 0
7fa7870c5000-7fa7870c9000 rw-p 00000000 00:00 0
7fff81245000-7fff8125a000 rw-p 00000000 00:00 0                          [stack]
7fff81336000-7fff81337000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
./t.sh: line 2: 25356 Aborted                 (core dumped) ./tm

我的代码:

*********
  tm.h
*********

#include <stdio.h>

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifndef TM_H
#define TM_H

#define NUM_COINS 6
#define TICKET_NAME_LEN 40
#define TICKET_ZONE_LEN 10
#define TICKET_TYPE_LEN 10
#define DEFAULT_STOCK_LEVEL 10
#define DEFAULT_COINS_COUNT 50
#define NUM_ARGS 3
#define MAX_LINE_SIZE 1024
#define DELIMITER ","

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;
};


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;
};


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;

#endif

#include "tm.h"

int main() {

    tm_type tm;
    tm_type * tm_ptr;
    tm_ptr = &tm;

    system_init(&tm);

    load_data(&tm, "stock.csv", "coins.csv");

    purchase_ticket(&tm);

    system_free(tm_ptr);

    exit(0);
}


void purchase_ticket(tm_type * tm) {

   struct stock_data user_input, compare;

   int stock_count = 0, x;
   int xxx[NUM_COINS] = { 5,10,20,50,100,200 };

   stock_count = tm->stock->num_stock_items;

   system("clear");

   for (x = 0; x < NUM_COINS; x++) { printf("\n%3d = %2d", xxx[x], tm->coins[x].count); }
   printf("\n\n");

   for (x = 0; x < NUM_COINS; x++) { printf("\n%3d = %2d", xxx[x], tm->coins[x].count); }
   printf("\n\n");   

   while (getchar() != '\n'){}
   return;
}


void load_data(tm_type * tm, char * stockfile, char * coinsfile)
{

   char temp_line[MAX_LINE_SIZE];
   char *token;
   int i, count = 0, number_coin, turn = 1;

   stock_node * snode = NULL;

   struct coin temp_coin[6];

   FILE *stock_file = fopen( stockfile, "r" );
   FILE *coins_file = fopen( coinsfile, "r" );

   while (fgets(temp_line, MAX_LINE_SIZE, stock_file) != NULL) {

      token = strtok (temp_line, DELIMITER);
      count++;

      snode = (stock_node *) realloc(snode, count * sizeof(stock_node));
      if (snode == NULL) { abort(); }  

      snode[count - 1].data = (struct stock_data *) calloc(1, sizeof(struct stock_data));

      if (snode[count - 1].data == NULL) { abort(); }   

      i = 1;

      while(token != NULL) {
         switch(i) {
            case 1:
               strcpy(snode[count - 1].data->ticket_name, token);
               break;
            case 2:
               snode[count - 1].data->ticket_type = token[0];
               break;
            case 3:
               strcpy(snode[count - 1].data->ticket_zone, token);
               break;
            case 4:
               snode[count - 1].data->ticket_price = atoi(token);
               break;
            case 5:
               snode[count - 1].data->stock_level = atoi(token);
               break;                                                            
         }
         token = strtok (NULL, DELIMITER);
         i++;
      }
   }

   struct stock_list slist = { snode, count };

   stock_list_ptr slist_ptr = &slist;

   tm->stock = slist_ptr;

   i = 0;

   while (fgets(temp_line, MAX_LINE_SIZE, coins_file) != NULL) {
      token = strtok (temp_line, DELIMITER);
      while(token != NULL) {
         token = strtok (NULL, DELIMITER);
         if(token != NULL) {
            sscanf(token, "%d", &number_coin);
         }

         if (turn == 1) {
            switch(number_coin) {
               case 5:
                  temp_coin[i].denomination = FIVE_CENTS;
                  break;
               case 10:
                  temp_coin[i].denomination = TEN_CENTS;
                  break;
               case 20:
                  temp_coin[i].denomination = TWENTY_CENTS;
                  break;
               case 50:
                  temp_coin[i].denomination = FIFTY_CENTS;
                  break;
               case 100:
                  temp_coin[i].denomination = ONE_DOLLAR;
                  break;
               case 200:
                  temp_coin[i].denomination = TWO_DOLLARS;
                  break;
            }

            turn = 2;

         } else {
            temp_coin[i].count = number_coin;
            turn = 1;
         }
      }

      i++;
   }   

   coin_list_ptr clist_ptr = (coin_list_ptr) malloc(sizeof(coin_list_ptr));
   if (clist_ptr == NULL) { abort(); }  

   clist_ptr = temp_coin;

   tm->coins = clist_ptr;

   fclose(stock_file);
   fclose(coins_file);

   return;
}


void system_free(tm_type_ptr tm) {
    free(tm->stock);
}

void abort () {
   exit(1);
}

CSV 文件:

Coins.csv   (<coin>, <coin_count>)
---------
5,10
10,5
20,8
50,2
100,20
200,8


Stock.csv    (<ticketName>,<type>,<zone>,<price>,<stockLevel>)
---------
2 hour,F,1,350,5
Weekly,C,1+2,2370,10
Daily,F,2,700,8
Weekly,F,1,1240,9
Daily,C,1,200,5
4

1 回答 1

2

你的问题在这个领域(可能在其他地方也有同样的问题,但这个问题对我来说很突出)

coin_list_ptr clist_ptr = (coin_list_ptr) malloc(sizeof(coin_list_ptr));
if (clist_ptr == NULL) { abort(); }  

clist_ptr = temp_coin;
tm->coins = clist_ptr;

var 'temp_coin' 是函数中本地定义的数组(也称为堆栈分配)。您将其设置为(最终)为从该方法返回的 tm 的成员。这很糟糕,因为在函数返回后堆栈内存被重用。您不能在离开函数的变量中返回在函数中本地分配的内存地址。局部变量是堆栈分配的,但返回的变量需要堆分配。如果您更改以下内容(在 load_data 中):

struct coin temp_coin[6];

struct coin temp_coin = malloc(6 * sizeof(coin));

你会有更好的结果。第一个 printf 循环正常工作的唯一原因是运气,如果代码有点不同,它很容易在那里打印损坏的值。

----- 从评论跟进 ----- 在您链接的帖子中,您有以下代码:

snode = (stock_node *) realloc(snode, count * sizeof(stock_node));
struct stock_list slist = { snode, count };
stock_list_ptr slist_ptr = (stock_list_ptr) malloc(sizeof(stock_list_ptr));
slist_ptr = &slist;
tm->stock = slist_ptr;

人们试图传达您不需要同时分配和初始化的信息。例如:

(1) struct stock_list slist = { snode, count };
(2) stock_list_ptr slist_ptr = (stock_list_ptr) malloc(sizeof(stock_list_ptr));
(3) slist_ptr = &slist;
(4) tm->stock = slist_ptr;

第 1 行为堆栈上的结构分配空间。第二行在堆上为结构分配空间。第三行用堆栈分配的内存覆盖堆分配内存的地址。第四行将堆栈分配的内存分配给您 tm->stock。这样做会更好:

stock_list_ptr slist_ptr = (stock_list_ptr) malloc(sizeof(stock_list)); // note sizeof(stock_list) not stock_list_ptr
if (slist_ptr == NULL) {/* error do something */ }
slist_ptr->head_stock = snode;
slist_ptr->num_stock_items = count;
tm->stock = slist_ptr;

希望这有助于清除它

于 2013-11-10T05:37:32.850 回答