2014-10-10 78 views
0

我越來越想運行下面的代碼時分段故障造成內存:分段故障核心用C傾倒在嘗試使用一個struct

C語言文件

#include <stdio.h> 
#include <stdlib.h> 
#include <stdarg.h> 
#include <string.h> 
#include "myData.h" 

struct structPointer *sP; 
struct structPointer *sSP; 
int recordNumber = 0; 
int numberOfAccesses = 0; 

int main(void) { 
    sP = (struct structPointer *) malloc(5 * sizeof(struct structPointer)); 
    sSP = sP; 

    memcpy(sP->name,"Adam Baum",50); 
    memcpy(sP->fireNumber,"N1234",10); 
    memcpy(sP->street,"Top Secret",25); 
    memcpy(sP->city,"Manhattan",25); 
    memcpy(sP->state,"New York",25); 
    sP++; 
    recordNumber++; 
    memcpy(sP->name,"Adam Zapel",50); 
    memcpy(sP->fireNumber,"S4321",10); 
    memcpy(sP->street,"Throat",25); 
    memcpy(sP->city,"Manhattan",25); 
    memcpy(sP->state,"New York",25); 
    sP++; 
    recordNumber++; 
    memcpy(sP->name,"Al Bino",50); 
    memcpy(sP->fireNumber,"W1234",10); 
    memcpy(sP->street,"White",25); 
    memcpy(sP->city,"Anchorage",25); 
    memcpy(sP->state,"Alaska",25); 
    sP++; 
    recordNumber++; 
    memcpy(sP->name,"Anne Teak",50); 
    memcpy(sP->fireNumber,"E4321",10); 
    memcpy(sP->street,"Oak",25); 
    memcpy(sP->city,"Woodville",25); 
    memcpy(sP->state,"Wisconsin",25); 
    sP++; 
    recordNumber++; 
    memcpy(sP->name,"Barb Dwyer",50); 
    memcpy(sP->fireNumber,"N1234",10); 
    memcpy(sP->street,"Keepout",25); 
    memcpy(sP->city,"Kilgore",25); 
    memcpy(sP->state,"Texas",25); 
    recordNumber++; 

    while (1){ 
     int sel; 
     printf("MENU\n"); 
     printf("=====\n"); 
     printf("1. Print All Records\n"); 
     printf("2. Print Number of Records\n"); 
     printf("3. Print Size of Database\n"); 
     printf("4. Add Record\n"); 
     printf("5. Delete Record\n"); 
     printf("6. Print Number of Accesses to Database\n"); 
     printf("7. Exit\n"); 
     printf("=====\n"); 
     printf("Enter selection: "); 
     sel = getchar(); 
     sel = sel-48; 
     switch(sel){ 
      case 1: 
       numberOfAccesses++; 
       printAllRecords(sP); 
       break; 
      case 2: 
       numberOfAccesses++; 
       fprintf(stderr,"There are a Total of %d records\n", recordNumber); 
       break; 
      case 3: 
       numberOfAccesses++; 
       printSizeOfDatabase(sP); 
       break; 
      case 4: 
       numberOfAccesses++; 
       sP = sSP; 
       addRecord(sP); 
       break; 
      case 5: 
       numberOfAccesses++; 
       deleteRecord(sP); 
       break; 
      case 6: 
       numberOfAccesses++; 
       fprintf(stderr,"The total number of Accesses is %d\n", numberOfAccesses); 
       break; 
      case 7: 
       exit(0); 
      case -38: 
       printf("Code is reading in LineFeed and displaying Menu again\n"); 
       break; 
      default: 
       printf("Error: Input was not a valid selection.\n"); 
       break; 
     } 
    } 
return 0; 
} 

int printAllRecords(struct structPointer *addresses){ 
    int i; 
    printf("All Records: "); 
    for(i=1;i<recordNumber;i++){ 
     printf("Address: %d\n", i); 
     fprintf(stderr, "Name = \%s\n", addresses-> name); 
     fprintf(stderr, "Fire Number = \%s\n", addresses-> fireNumber); 
     fprintf(stderr, "Street = \%s\n", addresses-> street); 
     fprintf(stderr, "City = \%s\n\n", addresses-> city); 
     fprintf(stderr, "State = \%s\n\n", addresses-> state); 
    } 
    return 1; 
} 

int printSizeOfDatabase(struct structPointer *addressesAgain) { 
    int size = 0; 
    int i; 
     for (i=1;i<=recordNumber;i++) { 
     size += sizeof(addressesAgain->name); 
     size += sizeof(addressesAgain->fireNumber); 
     size += sizeof(addressesAgain->street); 
     size += sizeof(addressesAgain->city); 
     size += sizeof(addressesAgain->state); 
     addressesAgain++; 
     } 
    fprintf(stderr, "The size of the database is %d bytes.\n", size); 
    return size; 
} 

int addRecord(struct structPointer *addressesAgainTimes2){ 
    char entryName; 
    char entryFireNumber; 
    char entryStreet; 
    char entryCity; 
    char entryState; 
    recordNumber++; 
    struct structPointer *theStruct; 
    theStruct = (struct structPointer *) malloc ((recordNumber+1) * sizeof(struct structPointer)); 
    addressesAgainTimes2 = sSP; 
    int i; 
    for (i=1;i<recordNumber;i++){ 
     memcpy(theStruct->name,addressesAgainTimes2->name,50); 
     memcpy(theStruct->fireNumber,addressesAgainTimes2->fireNumber,10); 
     memcpy(theStruct->street,addressesAgainTimes2->street,25); 
     memcpy(theStruct->city,addressesAgainTimes2->city,25); 
     memcpy(theStruct->state,addressesAgainTimes2->state,25); 
     if(i==recordNumber-1){ 
      theStruct++;} 
     else{ 
      theStruct++; 
      addressesAgainTimes2++;} 
    } 
    printf("Enter the Name of the New Record: \n"); 
    scanf("%s",&entryName); 
    memcpy(theStruct->name,&entryName,50); 
    printf("Enter the Fire Number of the New Record: \n"); 
    scanf("%s",&entryFireNumber); 
    memcpy(theStruct->fireNumber,&entryFireNumber,10); 
    printf("Enter the Street of the New Record: \n"); 
    scanf("%s",&entryStreet); 
    memcpy(theStruct->street,&entryStreet,25); 
    printf("Enter the City of the New Record: \n"); 
    scanf("%s",&entryCity); 
    memcpy(theStruct->city,&entryCity,25); 
    printf("Enter the State of the New Record: \n"); 
    scanf("%s",&entryState); 
    memcpy(theStruct->state,&entryState,25); 
    addressesAgainTimes2=theStruct; 
    printf("Record has been added."); 
    return 0; 
} 

int deleteRecord(struct structPointer *addressesAgainTimes3){ 
    struct structPointer *anotherStruct; 
    anotherStruct = (struct structPointer *) malloc ((recordNumber+1) * sizeof(struct structPointer)); 
    int i; 
    for(i=0;i<5;i++){ 
     memcpy(anotherStruct->name,addressesAgainTimes3->name,50); 
     memcpy(anotherStruct->fireNumber,addressesAgainTimes3->fireNumber,10); 
     memcpy(anotherStruct->street,addressesAgainTimes3->street,25); 
     memcpy(anotherStruct->city,addressesAgainTimes3->city,25); 
     memcpy(anotherStruct->state,addressesAgainTimes3->state,25); 
     addressesAgainTimes3++; 
    } 
    addressesAgainTimes3=anotherStruct; 
    recordNumber--; 
    printf("Record has been deleted."); 
    return 0; 
} 

頭文件:

#include <stdio.h> 
#include <stdlib.h> 

struct structPointer{ 
    char *name; 
    char *fireNumber; 
    char *street; 
    char *city; 
    char *state; 
}; 

這個程序應該創建一個內存塊,我可以存儲一個結構並顯示一個菜單,我可以在該結構中添加/刪除條目。

+3

「memcpy(sP-> name,」Adam Baum「,50);」 - 此處的名稱未初始化,與所有其他結構成員相同。 – 2014-10-10 22:13:24

+0

你的調試器向你展示了什麼? – StarPilot 2014-10-10 22:13:26

+0

除了取消引用未初始化的指針外,還要複製出字符串的範圍。 'memcpy(sP-> name,「Adam Baum」,50)'將嘗試從一個10字節的字符串中複製50個字節。 – Barmar 2014-10-10 22:17:20

回答

1

您的structPointer成員字段是指向字符串的POINTERS,但它們從不分配任何內存。然後使用memcpy()實際上覆制到UNDEFINED內存。

更改您的結構爲將解決這一具體問題:

struct structPointer{ 
    char name[SOME_APPROPRIATE_NAME_LENGTH]; 
    char fireNumber[SOME_APPROPRIATE_NUMBER_LENGTH]; 
    char street[SOME_APPROPRIATE_STREET_LENGTH]; 
    char city[SOME_APPROPRIATE_CITY_LENGTH]; 
    char state[2]; 
}; 
+0

這樣解決了這個問題,謝謝!任何想法爲什麼它會在嘗試添加記錄後進行分割? (一旦我在輸入狀態後進入輸入) – Specerion 2014-10-10 22:33:22

+0

我剛剛注意到你使用了國家名稱而不是縮寫,那麼你在結構中爲國家分配了多少空間? – 2014-10-10 22:43:17

+0

我使用了狀態[26] – Specerion 2014-10-10 22:45:47

2

如果你不希望有初始化結構成員或單獨管理他們的記憶,那麼他們就應該數組來代替指針:

struct structPointer{ 
    char name[50]; 
    char fireNumber[10]; 
    char street[25]; 
    char city[25]; 
    char state[25]; 
}; 
+0

還要注意,您爲字符串的空尾字節保留空間。上面的大小對應於你的'memcpy()'長度,但是如果用作字符串,那麼這些數組容納比它們聲明的長度少一個字符。 – 2014-10-10 22:21:19

+0

非常有幫助,謝謝!它現在正在工作,直到我嘗試添加記錄。一旦我進入狀態,它會再次發生故障。有任何想法嗎? – Specerion 2014-10-10 22:27:31

+0

您僅爲五條記錄保留足夠的空間。如果您嘗試添加第六個,那麼您將最終在內存中寫入,而不是保留的塊的一部分。算你自己幸運,那會產生段錯誤。爲了解決這個問題,你可以嘗試'realloc()'來獲得一個更大的塊,或者你可以將你的結構數組轉換成一個鏈表,以每個結構爲基礎進行分配(和釋放)。 – 2014-10-13 16:28:14

0

當你初始化它時,你爲結構分配五次空間,但在結構中,char *(像名稱)是未分配的指針。你應該爲他們分配空間(並在清理時釋放它們)。無論是使用strdup還是使用malloc/memcpy。如果它們是固定大小,則將它們聲明爲固定大小的數組,然後它們也可以。

0

將您的結構成員作爲數組或在複製之前分別爲它們分配內存。