Jump to content
  • Advertisement
Sign in to follow this  
Ratslayer

Boost Regex fails to be instantiated

This topic is 2888 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I'm trying to use boost::regex to parse a .ASE file. However, the boost::regex class fails to instantiate somewhere in the middle of the parsing.
Here is some of my code:

//the actual parsing method
void Mesh::LoadASE()
{
sptr<SubMesh> submesh;
int nVertices, nFaces;
std::string::const_iterator bound;
Vec3 vtemp, vpos;
Mat33 mtransform;
Reader reader(FileName);
//jump into the first submesh
reader.JumpAfterNext("GEOMOBJECT");
while(!reader.eof())
{
reader.JumpAfterNext("NODE_TM");
//get the name of the submesh
reader.JumpAfterNext("NODE_NAME");
//generate a new submesh
submesh=sptr<SubMesh>(new SubMesh(reader.GetQuotedString()));
//get the matrix transform
reader.JumpAfterNext("TM_ROW0");
mtransform.setRow(0, reader.GetVec3());
reader.JumpAfterNext("TM_ROW1");
mtransform.setRow(1, reader.GetVec3());
reader.JumpAfterNext("TM_ROW2");
mtransform.setRow(2, reader.GetVec3());
//get the position
reader.JumpAfterNext("TM_ROW3");
vpos=reader.GetVec3();
//get buffer sizes
reader.JumpAfterNext("MESH_NUMVERTEX");
nVertices=reader.GetInt();
submesh->VertexBuffer=Buffer<real>(nVertices*3);
submesh->NormalBuffer=Buffer<real>(nVertices*3);
submesh->TextCoordBuffer=Buffer<real>(nVertices*2);
//get index buffer size
reader.JumpAfterNext("MESH_NUMFACES");
nFaces=reader.GetInt();
submesh->IndexBuffer=Buffer<unsigned int>(nFaces*3);
//get the vertices
for(int i=0;i<nVertices;i++)
{
reader.JumpAfterNext("MESH_VERTEX");
reader.JumpAfterNext("\\d+");
vtemp=reader.GetVec3();
submesh->Verticies.push_back(vtemp);
}
//get the indices
for(int i=0;i<nFaces;i++)
{
reader.JumpAfterNext("MESH_FACE");
reader.JumpAfterNext(":");
for(unsigned int j=0;j<3;j++)
//Fails somewhere here
submesh->IndexBuffer.p[i*3+j]=reader.GetInt();
}
//get the texCoords
reader.JumpAfterNext("MESH_NUMTVERTEX");
nVertices=reader.GetInt();
for(int i=0;i<nVertices;i++)
{
reader.JumpAfterNext("MESH_TVERT");
for(unsigned int j=0;j<2;j++)
submesh->TextCoordBuffer.p[i*2+j]=reader.GetReal();
}
SubMeshes.push_back(submesh);
//jump to next submesh
reader.JumpAfterNext("GEOMOBJECT");
}
}
//one of the Reader parsing functions
real Reader::GetReal()
{
//init the regex vars
boost::regex expression("(\\-?[\\d|\\.]+)"); //This is where it fails at some point
std::string::const_iterator start=CurPos, end=File.end();
boost::match_results<std::string::const_iterator> matches;
boost::match_flag_type flags = boost::match_default;
//get the real
real r;
if(boost::regex_search(start, end, matches, expression, flags))
{
start=matches[0].second;
string str=std::string(matches[1].first, matches[1].second);
r=string::alphaToReal(str);
}
CurPos=start;
return r;
}


I posted only one of the parsing functions, but that's because they are all the same. I basically duplicated the regex creating code in every single one of them and just altered the info extraction block.
As you can see, the LoadASE fails to create boost::regex somewhere around the middle, at index extraction. If I comment out the index extraction block, it will fail somewhere later. Can I not mindlessly instantiate the boost::regex classes over and over? Or is the problem somewhere else? Thank you.

Share this post


Link to post
Share on other sites
Advertisement


real Reader::GetReal()
{
//init the regex vars
boost::regex expression("(\\-?[\\d|\\.]+)"); //This is where it fails at some point
std::string::const_iterator start=CurPos, end=File.end();
boost::match_results<std::string::const_iterator> matches;
boost::match_flag_type flags = boost::match_default;
//get the real
real r;
if(boost::regex_search(start, end, matches, expression, flags))
{
start=matches[0].second;
string str=std::string(matches[1].first, matches[1].second);
r=string::alphaToReal(str);
}
CurPos=start;
return r;
}


When in doubt, pull out the part that you think is failing in to a tiny self-contained program. It's much easier to debug and explain that way. Do I need to care about the rest of your code here?

Are you sure you need to escape "-" with a preceding "\\" in your expression? By default boost::regex uses Perl syntax and according to this, hyphens don't need to be escaped.


As you can see, the LoadASE fails to create boost::regex somewhere around the middle, at index extraction.
[/quote]
What does this mean? A crash? A compilation error? An exception? If so, what kind?


If I comment out the index extraction block, it will fail somewhere later.
[/quote]
Again, "fail" has not been defined.


Can I not mindlessly instantiate the boost::regex classes over and over?
[/quote]
This shouldn't be a problem.



Share this post


Link to post
Share on other sites
Sorry for the confusion. Fail means heap corruption. It throws a Heap Dbg exception. Also, if I use boost::regex::assign instead of creating a boost regex copy, the effect is the same: the heap gets corrupted.
I have actually found the source of the problem - as always, I screwed something up, though I'm not sure what.

I have a class Buffer<T> that is a lightweight array container. Here is it's code:

template<typename T>
class Buffer
{
public:
Buffer(int size=0)
{
Size=size;
if(size)
p=new T[Size];
else p=0;
};
Buffer(std::vector<T> &vec)
{
Size=vec.size();
if(Size)
{
p=new T[Size];
for(unsigned int i=0;i<vec.size();i++)
p=vec.size;
}
else p=0;
};
Buffer(Buffer &buffer)
{
if(buffer.Size&&buffer.p)
{
Size=buffer.Size;
p=new T[Size];
for(unsigned int i=0;i<Size;i++)
p=buffer;
}
else Size=p=0;
};
~Buffer()
{
if(p)
delete[] p;
};
T *p;
unsigned int Size;
};

This is the IndexBuffer, VertexBuffer and TextCoorBuffer class you can see in the previous code.
I switched to std::vectors instead and everything works fine (Except being slow as hell). This class, however, does not and I really can not tell why. It often fails to instantiate the pointers properly and then to release the memory, resulting in crashes when I try to exit the program.
This is the class that causes heap corruption. What's wrong with it?

Share this post


Link to post
Share on other sites
In the constructor from an std::vector, surely you mean p = vec, not p = vec.size? This constructor should also take the vector argument by const reference.

The copy constructor should also take a Buffer by const reference.

You have omitted the operator[] for your buffer, so I can't critique that. This could be where the problem is.

You're missing an assignment operator, either in your code, or because you've neglected to show it here. You'll really need one of those if you don't have it already. EDIT: I now notice that you are indeed assigning Buffer objects in your code. I strongly suspect this is the cause of your problem.

Semi-colons aren't needed after the closing brace of method definitions.

You might not want to hear this, but I'd simply stick with std::vector. It's designed to be as efficient as possible. If you can write a replacement that's faster you're either not using vector correctly, or you should file a bug report with the STL implementor. Check that you don't have your standard library's debugging features enabled.

Have you run your code in a debugger? Can you find the line where the problem occurs?

Share this post


Link to post
Share on other sites
The debug line occurs at the destructor: delete[] p;. Every time that it happens the compiler tells me that the content of the pointer is unreadable (even though Size is set to something real and the pointer must have been instantiated).
I do not have an assignment operator, I thought that the automatic operator should work fine.
The Buffer(std::vector&) hasn't been used yet - it obviously would never compile with such stupid mistakes.
As far as using std::vector goes, it takes me about 3 second to parse a .ASE file with about 400 vertices. I can't say if it's because of the std::vector or because of bad regex usage or if it's even acceptable. I guess I'll stick to std::vectors for now, but I'm still curious about what mistake have I made.

Share this post


Link to post
Share on other sites

I do not have an assignment operator, I thought that the automatic operator should work fine.

It doesn't.

Consider carefully what happens when you do this:


Buffer<int> b1(100);
Buffer<int> b2(200);
b2 = b1;

// b2 destructor called
// b1 destructor called


First of all, in the assignment you've lost a handle on the 200 ints that b2 held before. Memory leak. Second, b1.p and b2.p now point to the same location. b2's destructor will delete[] that pointer and b1's destructor will delete[] it again.

I recommend reading about the rule of 3. That article actually implements something similar to your Buffer as an illustrative example. Knowing about the copy-and-swap idiom is also useful in this regard.

EDIT: If you're using Visual C++, it's probably worth googling for _SECURE_SCL and _HAS_ITERATOR_DEBUGGING.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!