I have been trying to get this bit of code to work without success. gdb tells me that there is a segfault somewhere in the void Compiler::GenerateCode_ToFile(char* filename) function, and I have manually traced the problem to somewhere in the line:
std::string tempfile = this->code->CodeGen( temp, AST_TYPE_UNDEF, symtab, 0);
but not after it or before it. Also, it seems to crash before any code of that virtual function is run.
Can anyone see the problem here? I just cant see what is causing it to crash. This is the function that calls the virtual function:
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 is the definition of the class represented by 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);
};
This is its superclass:
/// 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;};
};
and finally, this is the virtual function that is being called (although appears to crash before it is run):
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;
}
I know it crashes before it is run because the Sleep() never gets run.
Can anyone see the bug that is causing this mysterious segfault?
Thanks in advance.
The reason is that code
is not allocated or corrupted.
Check for nil
before running the function, then check if you can run any other function from that pointer. The first one will be obvious, the latter may mean the pointer got corrupted somewhere.
code
field and we might be able to help - Kornel Kisielewicz 2012-04-05 00:01
I see nowhere in your example where you actually allocate the Code
member variable. It is a pointer and what it points to needs to be allocated at some point.
There are other problems as well, though not directly related to your crash.
First, you never delete symtab
or temp
in GenerateCode_ToFile
. This is a memory leak. For that matter, why in the world are you dynamically allocating an int
there? Just declare an int on the stack and pass its address to the CodeGen
function. Same goes for symtab
if possible.
int i = 10;
SomeFuncThatTakesAPointer(&i);
Actually, looking more closely, you don't even use the int*
parameter in the function and it isn't saved anywhere, so just get rid of it entirely.
Next...
std::vector<ExprAST*>* Code;
Pointers to vectors and vectors that store pointers are almost always wrong. You are preventing the vector from handling dynamic memory allocation and deallocation for you. You may as well just use an array at this point (ok, an array doesn't grow for you if you assign something beyond its boundaries, but still, bad practice).
Vectors use a pattern called RAII to handle safely allocating and deallocating memory for you. When you maintain a pointer to a vector you circumvent that process and are required to call delete
on the vector yourself.
When you store pointers in a vector you, once again, prevent the vector from deallocating its stored objects. It will store the pointers themselves dynamically and call delete
on them, but this will not deallocate what the original pointer was pointing to.
C++ is a complex language. I suggest spending some time learning more about memory management in general and patterns like RAII which can simplify the process for you.
this->code
is a valid pointer - Oliver Charlesworth 2012-04-04 23:53