2014-10-18 1 views
-6

그래서 내 가정용 컴퓨터에서 잘 컴파일되는이 프로그램을 가지고 있지만, 대학 서버에서 컴파일하자마자 깨집니다. :/내 엉덩이에 엄청난 고통이 있습니다. 나는 어디서 또는 무엇이 오류를 일으키는지도 모른다. 대학에서 제기 한 valgrind 보고서로 처음 시작됩니다. 왜이 segfaulting 무엇입니까? 누군가 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에서 오류가 발생합니까?

다음 코드는 main입니다.

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

오류가 구조체에 있다고 생각합니다. 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): 
+0

가정에서 프로그램에서 valgrind를 실행 해보십시오. –

+0

@JimBalter 이것은 집에서 실행할 때 얻을 수있는 것입니다. (== 9814 == Memcheck, 메모리 오류 감지기 == 9814 == Copyright (C) 2002-2013 및 GNU GPL'd 줄리안 스워드 등 == Valgrind의-3.10.0.SVN 및 LibVEX를 사용하여 9814 ==, 저작권 정보 -h와 다시 실행 == 9814 == 명령 :. coins.dat ./main stock.dat == 9814 == 주 메뉴 : \t 1. 표시 항목 \t 2. 구매 항목 \t 3. 저장하고 종료 관리자 전용 메뉴 : \t 4. 항목 추가 \t 5. 제거 항목 \t 6. 디스플레이 동전 \t 7. 재설정 재고 \t 8.리셋 동전을 \t 9 중단 프로그램 은 옵션 (1-9)를 선택 : 디버그 정보 (전체 경고)와 –

+2

컴파일을하고 문제를 파악하기 위해 디버거에서 프로그램을 실행합니다. (오류는 load_data에서 발생하지만 반드시 버그가 있음을 의미하지는 않습니다.) – Mat

답변

6

Valgrind의는 불법 쓰기 Address 0x6172676f72502074에서 발생하는 것을 말한다.

해당 주소를 ASCII 문자로 보면 argorP t이거나 리틀 엔디안에서 변환 : t Progra입니다.

이것은 메뉴 항목 중 하나 인 "9. Abort Program"의 일부처럼 보입니다. 아마도 menu_init() 배열이 menu_items[] 배열 끝을 지나서 쓰고 있다는 버그일까요?

디버거에서 프로그램을 단계별 실행하면 문제를 빨리 찾아야한다고 생각합니다.

+2

@JoshuaTheeuf : 프로그램의 주소는 일반적으로 코드, 스택 또는 힙 중 하나에서 오는 특정 패턴을 가지고 있습니다. valgrind 또는 디버거 출력 ('0x402762','0x4028BE','0x7fffffffe6b4' 등)의 주소를 살펴보면'0x6172676f72502074'가 튀어 나오는 것을 알 수 있습니다. 주소가 이상하다고 판단되면 바이트 값 (0x61, 0x72, 0x67, 0x20 등)이 ASCII 문자 범위에있는 것처럼 보일 수도 있습니다. –

+0

좋은 눈 ... 나는 그 패턴을 항상 보았지만 그 모든 valgrind 출력에서 ​​빠져있었습니다. –