Crash / Segfault调用子类的虚拟成员

时间:2012-04-04 23:48:22

标签: c++ class segmentation-fault virtual

我一直试图让这些代码无法正常工作。 gdb告诉我在void Compiler :: 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-&gt;代码表示的类的定义。

/// 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()永远不会运行。

任何人都可以看到导致这种神秘段错误的错误吗?

提前致谢。

2 个答案:

答案 0 :(得分:1)

原因是code未分配或损坏。

在运行函数之前检查nil,然后检查是否可以从该指针运行任何其他函数。第一个是显而易见的,后者可能意味着指针在某处被破坏了。

答案 1 :(得分:1)

我在你的例子中看不到你实际分配Code成员变量的地方。它是一个指针,它指向的东西需要在某个时刻进行分配。

还有其他问题,但与您的崩溃没有直接关系。

首先,您永远不会删除symtab中的tempGenerateCode_ToFile。这是内存泄漏。就此而言,为什么你在世界上动态分配int呢?只需在堆栈上声明一个int并将其地址传递给CodeGen函数。如果可能,symtab也是如此。

int i = 10;
SomeFuncThatTakesAPointer(&i);

实际上,仔细观察,你甚至不在函数中使用int*参数,也不会在任何地方保存,所以只需完全摆脱它。

下一步...

std::vector<ExprAST*>* Code;

指向存储指针的向量和向量的指针几乎总是错误的。您正在阻止向量处理动态内存分配和释放。你可以在这一点上使用一个数组(好吧,如果你指定超出其边界的东西,数组不会为你增长,但仍然是不好的做法)。

Vectors使用名为RAII的模式来处理为您安全地分配和释放内存。当你维护一个指向向量的指针时,你会绕过那个过程,并且需要自己调用向量上的delete

当您将指针存储在向量中时,再次阻止向量释放其存储的对象。它将动态存储指针并在它们上调用delete,但这不会释放原始指针所指向的内容。

C ++是一门复杂的语言。我建议花一些时间来学习更多关于内存管理和RAII之类的模式,这可以简化你的过程。

相关问题