2016-05-10 9 views
-2

最近、C++オブジェクトの作成で問題が発生しました。この問題は多少問題のようですが、 C++ strange segmentation fault by object creation ですが、ここのコードはオープンソースプロジェクトの一部であり、簡単なエラーはないかもしれません。オブジェクト作成による別のC++の奇妙なセグメンテーションフォールト

オブジェクト作成はメソッドで呼び出され、メソッドは2つの連続ステップで呼び出されます。

クラスは次のようにstrtokenizer.hで定義されています

class strtokenizer { 
    protected: 
     vector<string> tokens; 
     int idx; 
    public: 
     strtokenizer(string str, string seperators = " "); 
     void parse(string str, string seperators); 
     int count_tokens(); 
     string next_token(); 
     void start_scan(); 
     string token(int i); 
}; 

をそしてstrtokenizer.cppで、それはこのようなものです:

using namespace std; 
strtokenizer::strtokenizer(string str, string seperators) { 
    parse(str, seperators); 
} 
void strtokenizer::parse(string str, string seperators) { 
    int n = str.length(); 
    int start, stop; 
    if (flag) { 
     printf("%d\n", n); 
    } 
    start = str.find_first_not_of(seperators); 
    while (start >= 0 && start < n) { 
     stop = str.find_first_of(seperators, start); 
     if (stop < 0 || stop > n) { 
      stop = n; 
     } 
     tokens.push_back(str.substr(start, stop - start)); 
     start = str.find_first_not_of(seperators, stop + 1); 
    } 
    start_scan(); 
} 
int strtokenizer::count_tokens() { 
    return tokens.size(); 
} 
void strtokenizer::start_scan() { 
    idx = 0; 
    return; 
} 
string strtokenizer::next_token() { 
    if (idx >= 0 && idx < tokens.size()) { 
     return tokens[idx++]; 
    } else { 
     return ""; 
    } 
} 
string strtokenizer::token(int i) { 
    if (i >= 0 && i < tokens.size()) { 
     return tokens[i]; 
    } else { 
     return ""; 
    } 
} 

次のようにstrtokenizerオブジェクトを作成する方法があります:

int dataset::read_wordmap(string wordmapfile, mapword2id * pword2id) { 
    pword2id->clear(); 
    FILE * fin = fopen(wordmapfile.c_str(), "r"); 
    if (!fin) { 
     printf("Cannot open file %s to read!\n", wordmapfile.c_str()); 
     return 1; 
    } 
    char buff[BUFF_SIZE_SHORT]; 
    string line; 
    fgets(buff, BUFF_SIZE_SHORT - 1, fin); 
    int nwords = atoi(buff); 
    for (int i = 0; i < nwords; i++) { 
     fgets(buff, BUFF_SIZE_SHORT - 1, fin); 
     line = buff; 
     strtokenizer strtok(line, " \t\r\n"); 
     if (strtok->count_tokens() != 2) { 
      continue; 
     } 
     pword2id->insert(pair<string, int>(strtok->token(0), atoi(strtok->token(1).c_str()))); 
    } 
fclose(fin); 
return 0; 

}

read_wordmap()メソッドが初めて実行されたとき(最初のread_wordmap()呼び出し)、 'strtok'オブジェクトは約87k回作成され、2回目(2回目のread_wordmap()呼び出し)にはオブジェクトは88K回以上実行することができます。しかし、それはラインで、第二のメソッド呼び出しでは約86Kの回でエラー(いつか「セグメンテーションフォールト」と時々「メモリの破損(速い)」を)上げます:

strtokenizer strtok(line, " \t\r\n"); 

とのコードブロックをオブジェクトの作成は以下のように改訂されますが、エラーはありません。

strtokenizer *strtok = new strtokenizer(line, " \t\r\n"); 
printf("line: %s", line.c_str()); 
if (strtok->count_tokens() != 2) { 
    continue; 
} 
pword2id->insert(pair<string, int>(strtok->token(0), atoi(strtok->token(1).c_str()))); 
+2

ようこそスタックオーバーフロー!デバッガを使用してコードをステップ実行する方法を学ぶ必要があるようです。良いデバッガを使用すると、プログラムを1行ずつ実行し、どこからずれているかを確認することができます。これはプログラミングをする場合に不可欠なツールです。さらに読む:[小さなプログラムをデバッグする方法](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/) –

+0

あなたの提案をお寄せいただきありがとうございます。私はデバッガを使用する方法を知っており、エラーが発生した行も書きました。より多くのデバッグ情報を提供する必要がありますか? – YongYoung

+0

クラッシュしたら、理想的には 'bt'(バックトレース)を行い、関連するローカル変数などの状態を調べるべきです。 –

答えて

0

コードにメモリが壊れているようです。 valgrind(http://valgrind.org/)のようなツールを使用して、コードが境界から書き出さないことを確認することを検討する必要があります。

修正されたコードでは、スタックメモリの代わりにヒープメモリを使用しています。これは、問題がまだ存在していても隠してしまう可能性があります。

コードを読んで、提供されたwordmapfileに予期しないデータがある場合の安全な取り扱いを保証するテストがいくつかあります。 たとえば、fgetsの結果をチェックしないので、ファイルの先頭にある単語の数が実際の単語の数よりも多い場合、問題が発生します。

+0

入力ファイルの最初の行の番号が入力ファイルの行の番号より大きい場合、最後の行がpword2idに複数回挿入されます。 –

0

私は@ Paul Rと他の友人の提案のもとで自分のコードを慎重にデバッグしました。 上記のコードは私のプロジェクトのごく一部です。プロジェクトでは、gibbsのサンプリングアルゴリズムは1000回(繰り返し)実行されることになっています。

各繰り返しで、古い行列は解放され、新しい行列は「新しいもの」になります。しかし、私はすべてのマトリックスとリストを解放することを忘れていたので、私のプログラムが壊れてしまったのです。

私は上記のコードを掲示した理由は、プログラムがラインに走ったたびにクラッシュするということです。

strtokenizer strtok(line, " \t\r\n"); 

オブジェクト「はstrtokは」10000で(ファイル1000の*行に対して実行されます+ライン)。だから、おそらく、あまりにも多くのオブジェクトが作成され、すべてのスタックメモリを占有していると思うようになりました。私は手動でそれらを解放する必要はないことが判明しましたが。

ビジュアルスタジオでプログラムをデバッグすると、メモリ占有率のモニタが各繰り返しで劇的に増加し、「bad_alloc」エラーが毎時発生しました。これらは、私が大きなダイナミックマトリックスを解放するのを忘れていることに気づきました。

ありがとうございました! あなたの時間を浪費する間違って記述された質問をお詫び申し上げます。