2014-12-07 48 views
0

這段代碼有問題。 它按預期工作,除了最終得到Seg故障。程序結束時出現分段錯誤

下面是代碼:

void distribuie(int *nrP, pach *pachet, post *postas) { 

    int nrPos, k, i, j; 
    nrPos = 0; 
    for (k = 0; k < 18; k++) 
     pos[k].nrPac = 0; 
    for (i = 0; i < *nrP; i++) { 
     int distributed = 0; 
     for (j = 0; j < nrPos; j++) 
      if (pac[i].idCar == pos[j].id) { 
       pos[j].vec[pos[j].nrPac] = pac[i].id; 
       pos[j].nrPac++; 
       distributed = 1; 
       break; 
      } 
     if (distributed == 0) { 
      pos[nrPos].id = pac[i].idCar; 
      pos[nrPos].vec[0] = pac[i].id; 
      pos[nrPos].nrPac = 1; 
      nrPos++; 
     } 
    } 
    for (i = 0; i < nrPos; i++) { 
     printf("%d %d ", pos[i].id, pos[i].nrPac); 
     for (j = 0; j < pos[i].nrPac; j++) 
      printf("%d ", pos[i].vec[j]); 
     printf("\n"); 
    } 

} 

並調用在主此功能()。

用gdb運行導致這個錯誤:

Program received signal SIGSEGV, Segmentation fault. 
0x00000001 in ??() 
+0

你對'gdb'會話做了回溯嗎? – WhozCraig 2014-12-07 16:27:11

+1

嘗試在其上運行valgrind ...你可能會把內存弄得一團糟 另外,爲什麼nrP是一個指向int的指針,如果你永遠不改變它的值? – Antzi 2014-12-07 16:27:30

+0

@Antzi與Valgrind的運行顯示了相同的: 過程與信號11(SIGSEGV)的默認操作終止 == 15484 ==訪問未映射區域內的地址0x0 == 15484 ==在爲0x1:??? HEAP內容: == 15484 ==在使用中在出口處:390個字節的10個塊 == 15484 ==總堆的使用情況:10個allocs,0的FreeS, 分配390個字節 == 15484 == == 15484 == LEAK SUMMARY: == 15484 ==絕對丟失:390個字節在10個塊中 – 2014-12-07 16:28:23

回答

1

如果gdb找不到堆棧跟蹤,這意味着你的代碼在堆棧中寫道如此徹底,無論是普通的C運行時也不gdb可以找到有關函數應該在堆棧上返回的位置的信息。

或換句話說,你有一個(主要)堆棧溢出。

某處,您的代碼寫入數組的邊界之外。令人好奇的是,代碼發佈引用全局變量pospac,但通過(未使用)變量postaspachet。它表明你所展示的代碼不是你正在執行的代碼。但是,假設pospac的拼寫與postaspachet的拼寫相同,則可能是因爲錯誤地處理了對您的distribuie()函數的調用。 (如果作爲一個意見建議,pospac真的是全局變量,那麼爲什麼功能獲得通過postaspachet?)

,能得到任何編譯警告?你是否啓用了編譯警告?如果你有GCC,代碼是否與-Wall一起幹淨地編譯?那麼-Wall -Wextra呢?如果您收到任何警告,請修復原因。記住,在你職業生涯的這個階段,C編譯器很可能比你更瞭解C語言。

通過打印鍵值(如*nrP)可以幫助您進行調試。如果這不是一個理智的價值,你知道從哪裏開始尋找。你也可以仔細看看這條線的數據:

pos[j].vec[pos[j].nrPac] = pac[i].id; 

有很多的空間,讓事情變得糟糕的誤入歧途!

1

我缺乏信息來完全幫助你:我不知道pos []數組的大小。與k < 18的循環表明它是18個元素(但它可能更少;我根本不知道)。然後你開始處理* nrP小包,但是你不檢查你最多處理了18個。如果還有更多,則會覆蓋其他一些內存。然後你想打印結果et瞧,一個分段錯誤,這意味着某些內存被損壞,被某人認爲是有效的pionter使用,但指針是無效的,...砰 - 段錯誤。

所以for循環至少應該檢查邊界(假設18):

for (i = 0; i < *nrP && i < 18; i++) { 

以相同的方式,在POS結構顯然有VEC的陣列,但其大小是未知的,並且由相同的推理可以是18,可以更少或更多:

pos[j].vec[pos[j].nrPac] 

如果您添加所有的邊界檢查,它可能會運行。

+0

pos數組的最大大小爲32.順便說一句,如果我將k循環到32,有時會出現Seg故障達到K = 19但並不總是......爲什麼? – 2014-12-07 17:53:15

+0

「最大尺寸32」(但可能更小)或「尺寸32」?內存不足的原因並不總是內存損壞,每次運行程序時都會有所不同。這種行爲是典型的內存腐敗。 – 2014-12-07 18:33:05