1

私はこのコードをうまく機能させようとしてきました。gdbは、voidCompiler :: GenerateCode_ToFile(char * filename)関数のどこかにセグメンテーション違反があることを教えてくれます。問題を手動で次の行のどこかにトレースしました。

 std::string tempfile = this->code->CodeGen( temp, AST_TYPE_UNDEF, symtab, 0);

しかし、その後や前ではありません。また、その仮想関数のコードが実行される前にクラッシュするようです。

誰かがここで問題を見ることができますか?何が原因でクラッシュするのかわかりません。これは、仮想関数を呼び出す関数です。

void Compiler::GenerateCode_ToFile(char* filename){

char directory[MAX_PATH];   //Actually represents the full path.
strcpy( directory, this->cwd.c_str());
strcat( directory, filename);

if(this->isVerboseMode)
    std::cout << "Source Output: " << directory << '\n';

std::fstream file( directory, std::ios::out);

int* temp = new int;
Symtable* symtab = new Symtable;
file << emit_core_code();
file << "\n\n";
std::string tempfile = this->code->CodeGen( temp, AST_TYPE_UNDEF, symtab, 0);
file.close();
}

これは、this->codeで表されるクラスの定義です。

/// CollectionExprAST - Expression class for multiple branches.
class CollectionExprAST : public ExprAST {
  std::vector<ExprAST*>* Code;
public:
  CollectionExprAST(std::vector<ExprAST*>* code) : Code(code) {}
  virtual std::string CodeGen(int* GeneratedCodeOpType,int WantOpType,Symtable* symtab, int depth);
  int GetType(void){return AST_TYPE_COLLECTION;};
  void* GetCollection(void){return this->Code;};
  void DebugPrint(int level);
};

これはそのスーパークラスです:

/// ExprAST - Base class for all expression nodes.
class ExprAST {
public:
  virtual ~ExprAST() {}
  virtual std::string CodeGen(int* GeneratedCodeOpType,int WantOpType,Symtable* symtab, int depth) {return std::string("");};
  virtual void DebugPrint(int level){return;};
  virtual int GetType(void){return AST_TYPE_UNDEF;};
  virtual void* GetCollection(void){return NULL;};
};

そして最後に、これは呼び出されている仮想関数です(実行される前にクラッシュするように見えますが):

std::string CollectionExprAST::CodeGen(int* GeneratedCodeOpType,int WantOpType,Symtable* symtab, int depth)
{
Sleep(3000);
std::string ret;
int j=0;
for(;j<this->Code->size();j++){
    int temp;
    int i=0;
    for(;i<depth;i++)
        ret += "\t";
    ret += (*this->Code)[j]->CodeGen(&temp,WantOpType,symtab, depth+1);
    ret += '\n';
}
return ret;
}

Sleep()は実行されないため、実行前にクラッシュすることはわかっています。

この不思議なセグメンテーション違反を引き起こしているバグを誰かが見ることができますか?

前もって感謝します。

4

2 に答える 2

1

その理由は、code割り当てられていないか、破損していないためです。

関数を実行する前に確認してnilから、そのポインターから他の関数​​を実行できるかどうかを確認してください。前者は明らかですが、後者はポインタがどこかで破損したことを意味する場合があります。

于 2012-04-04T23:54:49.480 に答える
1

あなたの例では、実際にCodeメンバー変数を割り当てる場所はどこにもありません。これはポインタであり、それが指すものは、ある時点で割り当てる必要があります。

クラッシュに直接関係するわけではありませんが、他にも問題があります。

symtabまず、またはtempを削除することはありませんGenerateCode_ToFile。これはメモリリークです。さらに言えば、なぜ世界で動的にintそこに割り当てているのですか?スタックでintを宣言し、そのアドレスをCodeGen関数に渡すだけです。可能であれば同じことがsymtab言えます。

int i = 10;
SomeFuncThatTakesAPointer(&i);

実際、もっとよく見るとint*、関数でパラメーターを使用することすらなく、どこにも保存されないので、完全に削除してください。

次...

std::vector<ExprAST*>* Code;

ベクトルへのポインタとポインタを格納するベクトルは、ほとんどの場合間違っています。ベクターが動的メモリ割り当てと割り当て解除を処理できないようにしています。この時点で配列を使用することもできます(境界を超えて何かを割り当てた場合、配列は拡張されませんが、それでも悪い習慣です)。

ベクターは、R​​AIIと呼ばれるパターンを使用して、メモリの安全な割り当てと割り当て解除を処理します。ベクトルへのポインタを維持すると、そのプロセスを回避し、自分でベクトルを呼び出す必要がありdeleteます。

ポインタをベクトルに格納するときは、もう一度、ベクトルが格納されているオブジェクトの割り当てを解除しないようにします。ポインタ自体を動的に格納して呼び出しdeleteますが、元のポインタが指していたものの割り当てを解除することはありません。

C++は複雑な言語です。一般的なメモリ管理や、プロセスを簡素化できるRAIIのようなパターンについて少し時間をかけて学ぶことをお勧めします。

于 2012-04-05T00:03:39.773 に答える