2011-06-03 45 views
1

我已經編寫了一個代碼來讀取文件,將其存儲在一個結構中並只顯示它。但不知何故,它給了我一個分段錯誤,我不知道爲什麼。有人可以幫幫我嗎?文件I/O中的分段錯誤

輸出:

file: /home/neel/map2.txt 
file opened 
Start Intersection 
a->road: 4 

a->roadId[0]: 1 
a->lane[0][0]: 2 
a->lane[0][1]: 2 

a->roadId[1]: 2 
a->lane[1][0]: 2 
a->lane[1][1]: 2 

a->roadId[2]: 3 
Segmentation fault 

代碼:

#include <iostream> 
#include <fstream> 
#include <stdio.h> 
using namespace std; 

struct Intersection 
{ 
    unsigned short road; 
    long long int *roadId; 
    short *lane[2]; 
}; 

int main(int argc, char** argv) 
{ 
    std::ifstream file; 
    cout<<"file: "<<argv[1]<<endl; 
    file.open(argv[1], std::ios::in); 
    cout<<"file opened"<<endl; 

    while (!file.eof()) 
    { 
    cout<<"Start Intersection"<<endl; 
    Intersection *a = new Intersection; 
    file>>a->road; 
    a->roadId = new long long int[a->road]; 
    a->lane[0] = new short[a->road]; 
    a->lane[1] = new short[a->road]; 
    cout<<"a->road: "<<a->road<<endl; 
    for (int i=0; i<a->road; i++) 
    { 
     file>>a->roadId[i]; 

     cout<<endl<<"a->roadId["<<i<<"]: "<<a->roadId[i]<<endl; 
     file>>a->lane[i][0]; 
     cout<<"a->lane["<<i<<"][0]: "<<a->lane[i][0]<<endl; 
     file>>a->lane[i][1]; 
     cout<<"a->lane["<<i<<"][1]: "<<a->lane[i][1]<<endl; 
    } 
    cout<<"Intersection inserted"<<endl; 
    delete a; 
    } 
} 

文本文件:

4 

1 
2 
2 

2 
2 
2 

3 
2 
2 

4 
2 
2 
+0

file >> a-> lane [i] [0]; 這看起來不對。 a-> lane是一個二維數組,其中第一個索引是0或1,第二個索引是從0 - >#道路(-1) – Joe 2011-06-03 21:33:20

回答

6

lane是2個元件的陣列,然而,當i在內部循環達到2您正在嘗試打印a->lane[2][0],這不存在。

+0

啊,我明白了。我犯了一個愚蠢的錯誤。它應該是文件>>車道[0] [我]而不是文件>>車道[我] [0] ..感謝您的幫助。 – 2011-06-03 21:34:30

2
file>>a->lane[i][0]; //wrong 
file>>a->lane[i][1]; //wrong 

該指數應反向:

file>>(a->lane[0][i]); //correct 
file>>(a->lane[1][i]); //correct 

我加了括弧只是清晰度。

此外,程序中有內存泄漏。應該有儘可能多的delete,因爲有new語句,以確保沒有內存泄漏。所以寫下這些:

delete [] a->roadId; 
delete [] a->lane[0]; 
delete [] a->lane[1]; 
delete a; //you've written only this! 

注意delete a應該是釋放內存時的最後一條語句!

+0

非常感謝您指出這個錯誤.. :) – 2011-06-05 04:12:10

2

我不是故意的,但是這個代碼有足夠的問題,幾乎很難決定從哪個開始。

using namespace std; 

這是第一個紅旗。關於我所能說的是,using namespace std;是一個可憐的主意。與其他命名空間可以接受,但是std,它應該始終避免(IMO)。

struct Intersection 
{ 
    unsigned short road; 
    long long int *roadId; 
    short *lane[2]; 
}; 

這讓我覺得這是一個設計相當糟糕的結構。 std::vector是一件好事。用它。您可能需要考慮爲您的結構類型定義operator>>,而不僅僅是一個愚蠢的數據結構,所以您可以直接閱讀。即使你不這樣做,從你使用它的方式,你真正需要的是更多的東西一樣:

struct road { 
    long long Id; 
    short lane[2]; 
}; 

struct Intersection { 
    int road_count; 
    road *roads; 
}; 

然後,而不是幾個平行陣列的所有相同的尺寸必須平行走,你會得到許多道路,每條道路都有自己的數據。儘管如此,std::vector仍然更好。

int main(int argc, char** argv) 
{ 
    std::ifstream file; 
    cout<<"file: "<<argv[1]<<endl; 
    file.open(argv[1], std::ios::in); 

而不是定義一個ifstream的對象,然後分別打開它,你應該通常計劃上傳遞名稱的構造函數,所以它定義在一個操作中打開,是這樣的:

std::ifstream file(argv[1]); 

但是,你也通常要添加一些錯誤檢查,所以你只嘗試使用命令行參數爲文件名,如果一個已經過去了,這樣的事情:

if (argc < 2) { 
     std::cerr << "Usage: your_command <filename>\n"; 
     return EXIT_FAILURE; 
    } 

然後你會有代碼來定義ifstream

while (!file.eof()) 

這是另一個主要問題。這種形式的循環基本上總是錯誤的(包括這種情況,從外觀上看)。

cout<<"Start Intersection"<<endl; 
    Intersection *a = new Intersection; 

似乎沒有理由動態分配它。你是否也許正在恢復(或者不恢復)Java或C#程序員? Java要求動態地分配用戶定義的類的所有對象,但C++不會。

file>>a->road; 
    a->roadId = new long long int[a->road]; 
    a->lane[0] = new short[a->road]; 
    a->lane[1] = new short[a->road]; 
    cout<<"a->road: "<<a->road<<endl; 
    for (int i=0; i<a->road; i++) 
    { 
     file>>a->roadId[i]; 

     cout<<endl<<"a->roadId["<<i<<"]: "<<a->roadId[i]<<endl; 
     file>>a->lane[i][0]; 
     cout<<"a->lane["<<i<<"][0]: "<<a->lane[i][0]<<endl; 
     file>>a->lane[i][1]; 
     cout<<"a->lane["<<i<<"][1]: "<<a->lane[i][1]<<endl; 
    } 

我寧願單獨從顯示數據的代碼中讀取數據的代碼。除了作業(或調試)之外,您在閱讀時很少要顯示大量原始數據。在任何情況下,讀取代碼通常應該存在於該類別的operator>>中,以及該類別的operator<<中的顯示代碼。

cout<<"Intersection inserted"<<endl; 

這似乎是一個徹頭徹尾的謊言。你實際上沒有插入Intersection任何東西。

delete a; 

當您退出動態分配Intersection,你就可以消除這一點。如果您堅持要手動處理所有動態分配,則需要在此之前刪除組件,以避免發生內存泄漏(另一個原因更喜歡std::vector)。

我知道這聽起來很負面,這讓我有點撕裂。一方面,我真的建議更好的方法來做事情。同時,這看起來足夠像作業,我非常猶豫,只是發佈更好的代碼。我試圖提供一些有關更好方法的提示,但意識到它們可能不是特定的 - 我爲此道歉,但考慮到這可能是作業,我認爲我不能成爲一名作家很多更具體。

+0

感謝您的詳細評論,我非常感謝。我將我的實際代碼簡化爲此代碼,以突出顯示問題。我的實際代碼非常複雜,包括數據結構。我不需要在這裏動態分配內存,但是在我的代碼中沒有其他選擇。我在編程方面有很多經驗,但一段時間以來一直處於失控狀態,因此編程風格很糟糕。你指出的大部分內容已經被合併到我的代碼中,當我試圖減少代碼長度時,這些代碼已經被嵌入到了我的代碼中。非常感謝您的幫助。 – 2011-06-05 04:10:39