这为什么会这么分裂?有人可以解释valgrind错误吗?

时间:2014-10-18 07:04:28

标签: c memory-leaks struct segmentation-fault valgrind

所以我有这个程序可以在我的家用机器上编译好,但是一旦我在大学服务器上编译它就会打破......:/这对我的屁股来说是一个巨大的痛苦。我不知道可能导致错误的位置或原因。我首先从大学的valgrind报告开始。

    ==13527== Memcheck, a memory error detector
==13527== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==13527== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==13527== Command: ./main stock.dat coins.dat
==13527== 
==13527== Invalid write of size 8
==13527==    at 0x402762: load_data (in /RMIThome/shr/5/s3234575/Assignments2/main)
==13527==    by 0x4028BE: main (in /RMIThome/shr/5/s3234575/Assignments2/main)
==13527==  Address 0x6172676f72502074 is not stack'd, malloc'd or (recently) free'd
==13527== 
==13527== 
==13527== Process terminating with default action of signal 11 (SIGSEGV)
==13527==  General Protection Fault
==13527==    at 0x402762: load_data (in /RMIThome/shr/5/s3234575/Assignments2/main)
==13527==    by 0x4028BE: main (in /RMIThome/shr/5/s3234575/Assignments2/main)
==13527== 
==13527== HEAP SUMMARY:
==13527==     in use at exit: 4,096 bytes in 19 blocks
==13527==   total heap usage: 19 allocs, 0 frees, 4,096 bytes allocated
==13527== 
==13527== LEAK SUMMARY:
==13527==    definitely lost: 1,868 bytes in 8 blocks
==13527==    indirectly lost: 0 bytes in 0 blocks
==13527==      possibly lost: 0 bytes in 0 blocks
==13527==    still reachable: 2,228 bytes in 11 blocks
==13527==         suppressed: 0 bytes in 0 blocks
==13527== Rerun with --leak-check=full to see details of leaked memory
==13527== 
==13527== For counts of detected and suppressed errors, rerun with: -v
==13527== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)

所以错误是说它发生在主?但是直到它到达load_data函数才会显示,或者是否在main中调用load_data时发生错误?

以下代码为主。

#define _GNU_SOURCE
#include "assert.h"
#include <math.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vm_menu.h"
#include "vm_utility.h"
#include "vm_options.h"
#include "vm_type.h"


#define NUMARGS 3

struct menu_item * displayMenu(struct menu_item * menu, struct vm * vendMachine);
int main(int argc, char * argv[])
{
    struct vm *vm;
    vm = malloc(sizeof(struct vm));
    struct vm *vend;
      vend = malloc(sizeof(struct vm));
    struct menu_item menu_items[NUM_MENU_ITEMS]; 
 /*check if there are at least 3 arguments being passed through the command line */

    if(argc!=3)
    {
        printf("Insuffcient arguments \n");
        return EXIT_SUCCESS;
    }
    menu_init(menu_items);
    /* initialise the vm */
    vm_init(vm);

    load_data(vm, argv[1], argv[2]);
    vend->item_list.head = vm->item_list.head;
    BOOLEAN RUNNING = TRUE;

while(RUNNING){


        vm->item_list.head = vend->item_list.head;

    fflush(stdout);
    fflush(stdin);
    displayMenu(menu_items, vm);
}
    read_rest_of_line();
    return EXIT_SUCCESS;
 }

我认为错误发生在struct menu_item menu_items [NUM_MENU_ITEMS];因为我没有把它初始化为任何东西。但我不确定如何使用malloc将内存分配给一组结构?

加载数据文件是;

#include "vm_utility.h"


/* print list */
    void print_list(struct vm_node  *root) {
        while (root) {
            printf("%s",root->data->id);
            root = root->next;
        }
        printf("\n");
    }
/*creates a item and initialise the values */

struct stock_item* setupNode(char *line) {
    struct stock_item *root;
    root = malloc(sizeof(struct stock_item));
    char *ptr;
    char *ptrs;
    const char del[2] = "|";
    const char delm[2] = ".";
    char *prices;
    strcpy(root->id, strtok_r(line, del, &ptr)); // returns the ID and stores in in the root node.
    strcpy(root->name, strtok_r(NULL, del, &ptr)); // returns the description and stores it in the root node.
    strcpy(root->description, strtok_r(NULL, del, &ptr)); // returns the description and stores it in the root node.
    prices = strtok_r(NULL, del, &ptr); // returns a string of the price for vm_item.
    char *dols = strtok(prices, delm);
    char *cents = strtok(NULL, delm);
    long int dol = strtol(dols,&ptrs,10);
    long int cent = strtol(cents, NULL, 10);
    root->price.dollars = dol;
    root->price.cents = cent;
    int quantity = strtol(strtok_r(NULL, del, &ptr), NULL, 10); // returns how many items are in stock.
    root->on_hand = quantity;
    return root;

}

/*creates the list within the vm->item_list*/
int addNodeBottom(char *val, struct vm_node *head){

    //create new node
    struct stock_item *data;
    data = malloc(sizeof(struct stock_item));
    data = setupNode(val);


    if (head->data == NULL)
        head->data = data;
    else
    {
        struct vm_node *current = NULL;
        for (current = head; current->next != NULL; current = current->next)
            ;

        current->next = malloc(sizeof(*current->next));
        current->next->data = data;
        current->next->next = NULL;
    }

    return 0;
}

/*creates coin array stores in vm->coins; */
struct coin * addCoins(char *val){
    char *ptr =NULL;
    char *ptrs =NULL;
    const char *deli = ",";
    char *denominations = strtok_r(val, deli, &ptrs);
    char *counts = strtok_r(NULL, deli, &ptrs);

    long int denomination = strtol(denominations, &ptr,10);
    long int count = strtol( counts,NULL, 10);

    struct coin *k;
    k = malloc(sizeof(struct coin));
    k->denom = denomination;
    k->count = count;
    return k;
}

/* 
 * Clears the input buffer.
 * */
void read_rest_of_line(void)
{
    int ch;
    while(ch = getc(stdin), ch!='\n' && ch != EOF)
        ;
    clearerr(stdin);

}

/* 
 * Initialises the vm data structure declared in main to safe initial
 * values.
 * */
BOOLEAN vm_init(struct vm * vm)
{
    struct vm_node * vmNode;
    vmNode = malloc(sizeof(struct vm_node));
    vmNode->next = NULL;
    vmNode->data = NULL;
    vm->item_list.head = NULL;
    vm->coinsfile = NULL;
    vm->foodfile = NULL;
    return FALSE;
}

/* 
 * Loads data from the .dat files into memory. 
 * */
BOOLEAN load_data(struct vm * vm, const char * item_fname, 
        const char * coins_fname){

    FILE *file;
    file = fopen(item_fname, "r+");
    char buf[256];
    struct vm_node *vmNodes;
    vmNodes = malloc(sizeof(struct vm_node));
    vmNodes->data = NULL;
    vmNodes->next = NULL;

    while (fgets(buf, sizeof buf, file) != NULL) {
        addNodeBottom(buf,vmNodes);
    }
    vm->item_list.head = vmNodes;

    fclose(file);
    /*now open coin file*/

    FILE *fileCoin;
    fileCoin = fopen(coins_fname, "r+");
    char bufCoin[256];
    int i = 0;
    //vmNode->next = NULL;
    struct coin *j;
    while (fgets(bufCoin, sizeof bufCoin, fileCoin) != NULL) {

        j = addCoins(bufCoin);
        vm->coins[i] = *j;
        free(j);
        i++;
    }
    /**/
    /* Test reason for reaching NULL. */
        fclose(fileCoin);

    return FALSE;
}

/* 
 * Frees all dynamically allocated data.
 * */
void system_free(struct vm * vm)
{
    /* The UNUSED() function is designed to prevent warnings while your
     * code is only partially complete. Delete this function call once
     * you are using vm in your own code */

}

同样为了让生活更轻松,请分享所有结构的typedef。

    typedef enum truefalse
{
    FALSE, TRUE
} BOOLEAN;

/* Each price will have a dollars and a cents component */
struct price
{
    unsigned dollars,cents;
};

/* The different denominations of coins available */
enum denomination
{
    FIVE_CENTS, TEN_CENTS, TWENTY_CENTS, FIFTY_CENTS, ONE_DOLLAR, 
    TWO_DOLLARS, FIVE_DOLLARS, TEN_DOLLARS
};

/* Each coin in the coins array will have a denomination (20 cents, 
 * 50 cents, etc) and a count - how many of that coin do we have on hand
 */
struct coin
{
    enum denomination denom;
    unsigned count;
};

/* The data structure that holds the data for each item of stock
 */
struct stock_item
{
    char id[IDLEN+1];
    char name[NAMELEN+1];
    char description[DESCLEN+1];
    struct price price;
    unsigned on_hand;
};

/* The data structure that holds a pointer to the stock_item data and a
 * pointer to the next node in the list
 */
struct vm_node
{
    struct stock_item * data;
    struct vm_node * next;
};

/* The head of the list - has a pointer to the rest of the list and a 
 * stores the length of the list 
 */
struct vm_list
{
    struct vm_node * head;
    unsigned length;
};

/* This is the head of our overall data structure. We have a pointer to 
 * the vending machine list as well as an array of coins. 
 */
struct vm
{
    struct vm_list item_list;
    struct coin coins[NUMDENOMS];
    char * foodfile;
    char * coinsfile;
};

Valgrind在家:

    ==9814== Memcheck, a memory error detector
==9814== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==9814== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==9814== Command: ./main stock.dat coins.dat
==9814== 
Main Menu:
    1. Display Items
    2. Purchase Items
    3. Save and Exit
Administrator-Only Menu:
    4. Add Item
    5. Remove Item
    6. Display Coins
    7. Reset Stock
    8. Reset Coins
    9. Abort Program
Select your option (1-9):

1 个答案:

答案 0 :(得分:6)

Valgrind说非法写入发生在Address 0x6172676f72502074

如果您将该地址视为ASCII字符,则为:argorP t,或从小端转换:t Progra

这看起来像是您的一个菜单项的一部分,“9。中止程序”。也许错误是menu_init()正在写出menu_items[]数组的末尾?

我猜测在调试器中单步执行程序应该能够快速找到问题。