2016-03-24 49 views
0

申し訳ありませんが、私は尋ねる何かが明らかであるかばかげている、私は約2週間C言語を学ぶ+ +です。通常の状況でstd :: ifstreamを使用すると、セグメンテーションフォルトが発生するのはなぜですか?

EDIT:問題が見つかりました。ファイルの出力では、すべてのスペースが別の文字に変更されています。誰かがこの質問を閉じることができますか?

私は仮想の従業員に関するデータを収集するプログラムを作成しようとしています。最近、私はファイルから読み込もうとしましたが、以下のコードを実行するたびに(セグメンテーションエラーが発生します)ブレークポイントを使用して、私はstd::ifstream file(filename)に絞った。私はそれをテストしてテストし、filename変数が問題ではないことを理解しました。文字列リテラルを使用しても、それでもフォールトが発生します。私が見つけたその他のもの:

- std::ifstream file(filename)を別にして、このファイルの変数を参照できない別のファイルに配置してください。

私はが存在しないこと、ファイルの名前入力したとき-Theセグメンテーションフォールトがが発生しない - その代わり、それは0(それが必要のような)、プリントError in opening file.(それが必要のような)をブレークポイントまでを取得して、それはすべきである)falseを返します。

これがなぜ起こっているのか、それを修正する方法を知っている人はいますか?これは数日間私を悩ませている。

(また、私はGでのUbuntu 14.04を使用しています++ 4.8 - 起動フラグ-std = C++ 1Y)

EDIT [OK]を、これは非常に奇妙なっています。私がやった最初のことは、すべての他の行のstd::coutを使って私のプログラムをデバッグすることでした。これにより、問題がstd::ifstreamに示されました。しかし、@ M.Mと@hydeの推薦の下で、Code :: Blocksデバッガを使ってプログラムを実行しました。セグメンテーション違反はemp->firstName = lineList[2]で発生しました。だから私はその行をコメントアウトしましたが、デバッガはまだ行が問題だと言っています!この問題は、であると言われています。コメントアウトライン!私はこれまで以上に混乱しています。

#include <string> 
#include <vector> 
#include <fstream> 
#include <sstream> 
#include <iostream> 
#include "baselibrary.h" 
struct Employee 
{ 
    int16_t id; // Employee ID 
    std::string lastName; // Employee's last name 
    std::string firstName; // Employee's first name 
    char middleInitial; // Employee's middle initial 
    int16_t age; 
    bool gender; // false is male, true is female 
    float salary; 
    int16_t experience; // # of years working at company 
    int16_t department; // Department from Departments:: 
}; 
std::vector<Employee> employeeArrayN; 
int empNumN{1}; 
//... tons of snipped out code ...// 
bool loadFromDatabaseFileN(){ 
    std::string filename; 
    std::cout << "Please enter filename to load (with extension): "; 
    std::getline(std::cin, filename); 
    std::ifstream file(filename); 
    std::cout << "Breakpoint 0!"; 
    if (!file){ 
     std::cout << "Error in opening file. "; 
     return false; 
    } 
    std::cout << "Breakpoint 1!"; 
    while (file) // ifstream returns 0 when reaching EOF - 0 is boolean false 
    { 
     // it's probably OK to ignore the code under here, but you never know... 
     std::string lineInput; 
     std::cout << "Breakpoint 2!"; 
     Employee *emp = new Employee; 
     std::cout << "Breakpoint 3!"; 
     ++empNumN; 
     std::cout << "Breakpoint 4!"; 
     std::getline(file, lineInput); 
     std::vector<std::string> lineList = splitString(lineInput, ' '); 
     int16_t tempId; 
     std::cout << "Breakpoint 5!"; 
     std::stringstream(lineList[0]) >> tempId; 
     emp->id = tempId; 
     emp->lastName = lineList[1]; 
     emp->firstName = lineList[2]; 
     char tempMInit; 
     std::stringstream(lineList[3]) >> tempMInit; 
     emp->middleInitial = tempMInit; 
     int16_t tempAge; 
     std::stringstream(lineList[4]) >> tempAge; 
     emp->age = tempAge; 
     bool tempGend; 
     std::stringstream(lineList[5]) >> tempGend; 
     emp->gender = tempGend; 
     float tempSalary; 
     std::stringstream(lineList[6]) >> tempSalary; 
     emp->salary = tempSalary; 
     int16_t tempExperience; 
     std::stringstream(lineList[7]) >> tempExperience; 
     emp->experience = tempExperience; 
     int16_t tempDepartment; 
     std::stringstream(lineList[8]) >> tempDepartment; 
     emp->department = tempDepartment; 
     employeeArrayN.resize(empNumN); 
     employeeArrayN[empNumN - 1] = *emp; 
     std::cout << "Added new employe: [ID " << emp->id << "] " << emp->lastName << ", " << emp->firstName << " " << emp->middleInitial << ". \n"; 
    } 
    file.close(); 
    return true; 
} 
//...snip...// 

//fix is a function I added just for this question, I wouldn't want to bother you with my monolithic actual function// 
void fix() 
{ 
    bool notGonnaUse = loadFromDatabaseFileN(); 
} 
+0

あなたのコードは未定義の動作のいくつかの可能なソースがあります。たとえば、おそらく 'lineList [8]'がベクトルの範囲外にあるか、おそらくは '>>'が失敗して不確定な値が残ってしまいます。 [あなたのコードをデバッグする]を試してください(http://ericlippert.com/2014/03/05/how-to-debug-small-programs/)。他の誰かがあなたのためにそれをデバッグしたければ、問題を与えた正確な入力ファイルとともに[MCVE](http://stackoverflow.com/help/mcve)を提供する必要があります。結果を再現する。 –

+0

あなたはメモリをリークします( 'new Employee'に対応する' delete'はありません)、セグメンテーションとは無関係かもしれません –

+0

あなたは入力ファイルを表示していません...また、デバッガを呼び出してコールスタックを調べます。 'std :: ifstream file(filename)'は、最初にメモリが破壊されない限り、クラッシュする可能性は非常に低いです。たとえば、インデックス8にアクセスする前に、 'lineList'が実際に9要素を持っていることを確認してください... – hyde

答えて

0

これは

while (file) 
{ 
    ... 
    std::getline(file, lineInput); 
    ... 
} 

使用して...

あなたの問題を解決しないかもしれませんが、が問題です。 Why is iostream::eof inside a loop condition considered wrong?を参照してください。使用するのと同じ問題から

while (file) { } 

被るの使い方

while (!file.eof()) { } 

変更することをコードに使用する:

// Move the declaration of lineInput out of the loop. 
std::string lineInput; 
while (std::getline(file, lineInput)) 
{ 
    ... 
} 
+0

注:これで問題が解決したとしても、元のクラッシュをデバッグし続けると良いでしょう。特定の入力ファイルを与えられただけでプログラムをクラッシュさせることはできません。これはセキュリティ上の脆弱性につながります。 –

+0

ありがとうございますが、これでも問題は解決しません。 –

+0

@PracticalProblems、私はあなたのコードで他の問題を見ることができません。分裂と征服のアプローチを試してみてください。 –

関連する問題