Re: C++ objects and flex
gus gassmann <gus@nospam.com> wrote in
news:kgufv2$uug$1@Kil-nws-1.UCIS.Dal.Ca:
Let me try this again, before the original message disappears from the
news server...
On 11/02/2013 4:46 PM, Jorgen Grahn wrote:
On Fri, 2013-02-08, Gus Gassmann wrote:
Not sure if this is a C++ question. If not, I apologize. Is there a
group where I could direct questions that deal with flex?
I don't think so. Most people use flex/bison rarely.
My situation is this: I have a (fairly complicated) C++ object (call
it Obj, perhaps) that I need to populate by parsing a string. I use
flex/bison to parse the string, and I currently have another C++
class, ObjReader, containing a method readObj(std::string objStr)
that calls the parser and stores the information read into the
various elements of a private member Obj* ObjReader->my_obj.
My problem is that I constantly get into memory trouble (variously
leaks and segfaults), because I ultimately want to access the data
from my own instance of Obj and often trigger (viz.,
construct/destruct) the reader in a subroutine.
I don't understand the reference to subroutines. I think you mean a
"function", but everything you do in C or in C++ is done in a
function!
OK. Fair enough. I guess my Fortran roots are showing. So let me try
again, with a little bit more of the code showing.
First, I have a complicated object class Obj, with code file Obj.cpp
and header file Obj.hpp. Let's say this consists of 5000 lines of
nested objects, and let's leave it at that. I hope I can explain the
rest without going into the details.
I then have an ObjReader class that looks like this:
ObjReader.hpp:
class ObjReader
{
public:
ObjReader();
~ObjReader();
Obj *readObj(const std::string &objstring);
private:
Obj* p_obj;
}
ObjReader.cpp:
#include "ObjReader.h"
//bison function
void yygetObj(const char *objstring, Obj* obj;
//lex functions
int objlex_init(void** ptr_yy_globals);
int objlex_destroy (void* scanner );
void objset_extra (void* yyscanner );
ObjReader::ObjReader( )
{
}
ObjReader::~ObjReader()
{
if(p_obj != NULL) delete p_obj;
p_obj = NULL;
}
Obj* ObjReader::readObj(const std::string& objstring)
{
if (objstring.length() > 0)
{
const char *ch = objstring.c_str();
yygetObj( ch, my_obj);
What is my_obj? Who creates the Obj object?
}
return p_obj;
}//end readObj
main.cpp:
void method1(Obj* my_obj);
void main()
{
Obj* my_obj = new Obj();
method1(obj);
}
void method1(Obj* my_obj)
{
ObjReader *objreader = new ObjReader();
No need to allocate ObjReader dynamically if it is only used locally.
my_obj = objreader->readObj("some XML string");
This does not make sense, the my_obj pointer is visible only inside this
function and main() never sees the read object. Also, the input parameter
value is never used.
}
I do want to get the parsing out of main, just to make the code more
structured and easier for me to read and maintain. (I did not create
the design, I just inherited it.)
My trouble is: I newed the objreader in method1, but obj is only a
pointer to the private p_obj in the objreader.
Hence I have two choices:
I do not call the ObjReader destructor in method1, and I have created
a memory leak;
I do call the ObjReader destructor in method1, and I have created a
segfault as soon as I try to do anything with my_obj outside of
method1.
It seems you are confused over object ownership. If you are passing
dynamically allocated objects around a lot and the ownership is not
clear, then the easiest solution is to slam some kind of a smartpointer
(e.g. std::shared_ptr or boost::shared_ptr) to do the job automatically
(and simplify the code as there should be no 'delete' lines any more).
// In C++11
#include <memory>
typedef std::shared_ptr<Obj> ObjPtr;
class ObjReader
// ...
ObjPtr p_obj;
};
ObjPtr method1() {
ObjReader objreader;
return objreader.readObj("some XML string");
}
hth
Paavo