2012-07-29 19 views
0

我最近註冊的USACO在線培訓計劃,我目前的問題2. 我已經完成編寫這一切都正確編譯。但是,當我提交代碼時,我不斷收到以下錯誤:運行時錯誤:非法文件打開(的/ dev/tty的)

運行1:執行錯誤:您的程序有此運行時錯誤: 非法文件打開(/ dev/tty)。該程序在錯誤發生前運行0.011 CPU 秒。它使用了3348 KB的內存。

我試圖尋找是徒勞的問題。但是,我認爲這是一個內存管理問題,因爲我使用了指針向量。在USACO常見問題解答中,他們說:

運行我們的評分系統的Linux比內存訪問更挑剔。因此,在Windows上允許的無效數組索引和錯誤的指針取消引用可能會導致您的程序在Linux下崩潰。或者,他們會破壞內部數據結構並給出最隱祕的錯誤消息,如「無法打開/ dev/[嘟嘟]」。

下面的代碼:

/* 
ID: freebie1 
PROG: gift1 
LANG: C++ 
*/ 
#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 
#include <fstream> 
using namespace std; 


class Person { 
    public: 
    Person():m_volatile(0) {} 

    void setName(string name) { m_name = name; } 
    string getName() { return m_name; } 
    void setMoney(int money){ m_sMoney = money; } 
    int getMoney() { return m_volatile; } 
    void receive(int money) { m_volatile += money; } 
    void giveGifts(vector<Person*> fTab){ 
     int splitMoney = m_sMoney/fTab.size(); 
     for(vector<Person*>::iterator it=fTab.begin();it!=fTab.end();it++) { 
      (*it)->receive(splitMoney); 
     } 
     m_volatile-=splitMoney*fTab.size(); 
    } 

    private: 
    string m_name; 
    int m_sMoney; // starting money 
    int m_volatile; 
}; 

class FindFriend { 
    public: 
    FindFriend(string query):m_query(query){} 
    bool operator()(Person &individu){ 
     if(individu.getName()==m_query) { return true; } 
     else { return false; } 
    } 
    private: 
    string m_query; 
}; 

vector<Person*> setFriends(vector<string> &namesTab,vector<Person> &personsTab){ 
    vector<Person*> tab; 
    for(vector<string>::iterator it=namesTab.begin();it!=namesTab.end();it++) { 
     FindFriend f(*it); 
     vector<Person>::iterator trouve=find_if(personsTab.begin(),personsTab.end(),f); 
     tab.push_back(&*trouve); 
    } 
    return tab; 
} 

int main() { 
    ofstream fout("gift1.out"); 
    ifstream fin("gift1.in"); 

    if(fin) { 
     int np(0); 
     fin>>np; // Number of persons 

     // Each one is assigned a name... 
     vector<Person> personsTab(np); 
     for(vector<Person>::iterator it=personsTab.begin();it!=personsTab.end();it++){ 
      string namePerson; 
      fin>>namePerson; 
      it->setName(namePerson); 
     } 
     // ...money and the friends we'll give the money to 
     while(!fin.eof()){ 
      string name; 
      int money(0),nFriends(0); 
      fin>>name; 
      FindFriend g(name); 
      vector<Person>::iterator trouve=find_if(personsTab.begin(),personsTab.end(),g); 
      fin>>money>>nFriends; 
      trouve->setMoney(money); // Somme de depart 
      // Amis 
      if(nFriends!=0 || money!=0) { 
       vector<string> friendsTab; 
       for(int i(0);i<nFriends;i++) { 
        string chaine; 
        fin>>chaine; 
        friendsTab.push_back(chaine); 
       } 
       // We create a vector of pointers to his friends 
       vector<Person*> pFriends(nFriends); 
       pFriends=setFriends(friendsTab,personsTab); 
       trouve->giveGifts(pFriends); // Each person share the money among his friends 
      } 
     } 

     // We output the net loss/profit for each one 
     for(vector<Person>::iterator it=personsTab.begin();it!=personsTab.end();it++) { 
      string name=it->getName(); 
      int money=it->getMoney(); 
      fout<<name<<" "<<money<<endl; 
     } 
    } 
    return 0; 
} 

這裏是gift1.in

5 
dave 
laura 
owen 
vick 
amr 
dave 
200 3 
laura 
owen 
vick 
owen 
500 1 
dave 
amr 
150 2 
vick 
owen 
laura 
0 2 
amr 
vick 
vick 
0 0 
+0

需要查看gift1.in的內容。我認爲最可能的錯誤不是指針向量,而是當你做find_if時,你從不檢查是否找到了你要找的東西。 – jahhaj 2012-07-29 11:16:45

回答

2

輸入文件的問題是,你是不是正確的測試文件結束。使用fin.eof()是錯誤的,因爲你已經嘗試閱讀和失敗後,eof()只爲真,但它確實預測下一個讀是否會失敗。有多少初學者弄錯了這一點令人難以置信。

這裏有一個更好的方式來做到這一點

string name; 
    while(fin >> name){ 
     int money(0),nFriends(0); 
     ... 
    } 

您的錯誤的結果是,你去圓while循環一次比你應該。在最後一次循環name不包含有效值,並且您致電find_if失敗並且程序不久之後崩潰。

0

我在這裏猜測,但在網上尋找文件描述我發現/ dev/tty是一個特殊的文件,用於在UNIX上向您的進程的控制終端窗口發送文本(參見:What is special about /dev/tty?)。

賠率是提交機制是服務,沒有父終端窗口中輸出文本,所以必須有正試圖輸出到標準輸出導致此問題的東西。

則很可能是某個錯誤正在由這個隱藏,因爲它試圖錯誤發送到屏幕上。如果您正在使用Windows計算機,我建議您購買一個VMware播放器(免費)並構建一個Linux VM(應該非常簡單,只需下載免費發行版並將VMware Player指向它),然後在該環境中編譯並運行您的程序所以你可以看到它的行爲。這樣你就可以看到它試圖告訴你什麼,並從那裏開始工作。

Bonne的機會。PS:我有一臺Linux機器,稍後我會自己嘗試一下,但是您應該經歷爲其他問題製作Linux VM的練習,因爲您很可能會再次遇到此問題。

然你的程序因爲是在Linux和輸出文件有:

dave 302 
laura 66 
owen -359 
vick 141 
amr -150 

它拋出該異常:

*** glibc detected *** ./test.out: free(): invalid pointer: 0x0000000001b43510 *** 
======= Backtrace: ========= 
/lib/x86_64-linux-gnu/libc.so.6(+0x7a6e6)[0x7f3dfaa846e6] 
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x6c)[0x7f3dfaa889cc] 
/usr/lib/x86_64-linux-gnu/libstdc++.so.6(_ZNSsD1Ev+0x23)[0x7f3dfb0641e3] 
./test.out[0x401ece] 
./test.out[0x404808] 
./test.out[0x40439d] 
./test.out[0x403d40] 
./test.out[0x403269] 
./test.out[0x40249c] 
./test.out[0x4019ae] 
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f3dfaa2b30d] 
./test.out[0x401169] 
... 

用gdb一行步驟線,異常發生,因爲「personsTab 「變量超出範圍並被破壞。

相關問題