Sign in to follow this  
marshdabeachy

Visual C++ INTERNAL COMPILER ERROR

Recommended Posts

Okay to start things off, this will likely make very little sense, because it was a struggle for me to get this working as far as I have. I'm getting an internal compiler error using Visual Studio .NET 2003. The specific error is this:
Quote:
c:\documents and settings\marshall\desktop\mode7\mode7.cpp(517): fatal error C1001: INTERNAL COMPILER ERROR (compiler file 'f:\vs70builds\3077\vc\Compiler\Utc\src\P2\main.c', line 148)
The code it appears to be nuking on is this line inside the for loop:
std::list<Tween*>::iterator iter;
for (iter = p.tweens.begin(); iter != p.tweens.end(); iter++) {
	// loop through tweens using this vomit inducing code
	(p.*(*iter)->setProp)( (*iter)->tweenFunct(p.GetLifeCurrent(), p.GetLifeMax(), (*iter)->elements) );
}
Yeah, not exactly the prettiest code. It was working before I templatized it, though. Basically, I've set up a way to handle tweens over time. Looks like this:
template <class T>
struct Tween {
	T (*tweenFunct)(float life, float maxLife, std::vector<T>& elements);
	std::vector<T> elements;
	void (Sprite::*setProp)(T value);
};

template<class T>
void Particle::SetTransition(T (*tween)(float life, float maxLife, std::vector<T>& elements), void (Sprite::*setProp)(T value), T* element, int length) {
	// add tween to list
	Tween* t = new Tween;
	t->tweenFunct = tween;
	t->setProp = setProp;
	t->elements.resize(length);
	for (int i=0; i<length; i++) {
		t->elements[i] = element[i];
	}
	tweens.push_back(t);
	// initialize property
	(this->*setProp)( (*tween)(1.0f, 1.0f, t->elements) );
}
Implementation looks like this:
unsigned elementsR[] = {0x00, 0xFF};
p->SetTransition(&LinearInTween<unsigned>, &Sprite::SetRed, elementsR, sizeof(elementsR));
It's a mess, I know. But the implementation is rather simple, and that's what I was going for. Previously, I had it passing the vectors by value, which was giving me a bizarre "cannot convert std::vector to std::vector" error. I switch it to pass by reference and now I'm getting an internal compiler error. If you somehow managed to understand this, do you have any idea what's going on, or more importantly, how to fix it? Many thanks in advance.

Share this post


Link to post
Share on other sites
I didn't read your code but is seems like you allocate too much memory some where there.
You allocate memory out of the limits of your compiler.
Try to read this article to understand more:
HERE

And wait to more suggestion from the people here :).

Share this post


Link to post
Share on other sites
Quote:
Original post by marshdabeachy

std::list<Tween*>::iterator iter;
for (iter = p.tweens.begin(); iter != p.tweens.end(); iter++) {
// loop through tweens using this vomit inducing code
(p.*(*iter)->setProp)( (*iter)->tweenFunct(p.GetLifeCurrent(), p.GetLifeMax(), (*iter)->elements) );
}



Is this the exact code? If so, that first line should be
std::list<Tween<T>*>::iterator iter;

Why it would produce an internal compiler error and not spew forth a mountain of real errors is beyond me though [smile]

Share this post


Link to post
Share on other sites
Quote:
p->SetTransition(&LinearInTween<unsigned>, &Sprite::SetRed, elementsR, sizeof(elementsR));
Shouldn't that be sizeof(elementsR)/sizeof(unsigned) to get the right count?

I don't have any ideas about the internal compiler error, though - sometimes they indicate bugs in your code, but sometimes just bugs in the compiler that you can't do anything about. If noone else has the answer already, it might be worth trying to compile in VS2005 or GCC, or posting a complete stripped-down example that demonstrates the problem.

Share this post


Link to post
Share on other sites
In my experience, an internal compiler error combined with template code means that your code is technically correct, but the compiler simply can't handle it. Sometimes simplifying the line causing the error can fix the problem. Try something like this:

Tween* t = *iter;
(p.*(t->setProp))( t->tweenFunct(p.GetLifeCurrent(), p.GetLifeMax(), t->elements) );

Share this post


Link to post
Share on other sites
Use source tags. And shorter lines. Not everyone gets to read code on a widescreen monitor.

Share this post


Link to post
Share on other sites
First let's make it a little less vomit-inducing. :)

Step 1: Make typedefs for the function-pointer types, and use them. Note that you don't need to name function parameters in these typedefs; function parameter *names* are never part of the function signature. Only the *types* matter.

Step 2: Make the Tween a little more intelligent by giving it an operator() which forwards to its tweenFunct. Actually, I'm going to rename that to remove the redundancy in naming.

Step 3: Reduce some of the &*&*ing syntax by making a reference inside the for-loop. Also pull out some of the loop invariants to remove focus from them.

That gives:


template <class T>
struct Tween {
typedef T (*FuncType)(float, float, std::vector<T>&);
FuncType func;
std::vector<T> elements;
typedef void (Sprite::*propertySetter)(T);
propertySetter setProp;

T operator(float life, float max) {
return func(life, max, elements);
}
};

template<class T>
void Particle::SetTransition(Tween<T>::FuncType tween, Tween<T>::propertySetter setProp, T* element, int length) {
// add tween to list
Tween* t = new Tween;
t->tweenFunct = tween;
t->setProp = setProp;
t->elements.resize(length);
for (int i=0; i<length; i++) {
t->elements[i] = element[i];
}
tweens.push_back(t);
// initialize property
(this->*setProp)( (*tween)(1.0f, 1.0f, t->elements) );
}

// And the interesting code...
std::list<Tween*>::iterator iter;
float life = p.GetLifeCurrent();
float max = p.GetLifeMax();
for (iter = p.tweens.begin(); iter != p.tweens.end(); iter++) {
Tween& t = **iter; // once to get the pointer, again for a reference
(p.t->setProp)(t(life, max));
}




Now we can look at that with our heads cocked:

1) How are you supposed to make a list of 'Tween*', when Tween is a templated type? You need to fill in the 'something' in 'list-of-pointers-to-tween-of-something'.

2) WTF is 'p.t' supposed to be now? 't' is a variable, not a member name. I think you wanted just 't->setProp'.

3) Except that t isn't a pointer now; so it's just 't.setProp'.

4) Except that setProp is a pointer to a *member* function, so we need to invoke it upon an object. That would make it something like 'mySprite.*(t.setProp)'. Okay, so I guess 'p' in your case was the Sprite? Sigh. I think you were just getting a bad parse because of the operator precedence. But really, you shouldn't try to write things like that. PMFs are weird enough as it is. In fact, let's pull that work into the Tween member function too.

So now we have:


template <class T>
struct Tween {
typedef T (*FuncType)(float, float, std::vector<T>&);
FuncType func;
std::vector<T> elements;
typedef void (Sprite::*propertySetter)(T);
propertySetter setProp;

void operator(Sprite& s, float life, float max) {
// The problem with '(p.*(*iter)->setProp)' is that it tries to make
// 'p.*(*iter)' be the bound-and-ready-to-call PMF, which is already
// garbage because *iter is a Tween* rather than a PMF, and then tries to
// dereference that and get a member instead of calling.
// Now that we have the rest of the code factored, this goes more smoothly:
(s.*setProp)(func(life, max, elements));
}
};

template<class T>
void Particle::SetTransition(Tween<T>::FuncType tween, Tween<T>::propertySetter setProp, T* element, int length) {
// add tween to list
Tween* t = new Tween;
t->tweenFunct = tween;
t->setProp = setProp;
t->elements.resize(length);
for (int i=0; i<length; i++) {
t->elements[i] = element[i];
}
tweens.push_back(t);
// initialize property
(*t)(*this, 1.0f, 1.0f);
}

// And the interesting code...
std::list<Tween*>::iterator iter;
float life = p.GetLifeCurrent();
float max = p.GetLifeMax();
for (iter = p.tweens.begin(); iter != p.tweens.end(); iter++) {
Tween& t = **iter; // once to get the pointer, again for a reference
t(p, life, max);
}




Finally, we figure out why there's this weird mismatch between 'Sprite' and 'Particle' types (which is part of what was throwing me off before). :) Oh, and why have that array-and-count interface? That's an ugly C throwback. Be generic and modern, and use an iterator pair (and add a constructor to the Tween):


template <class T>
struct Tween {
typedef T (*FuncType)(float, float, std::vector<T>&);
FuncType func;
std::vector<T> elements;
typedef void (Sprite::*propertySetter)(T);
propertySetter setProp;

void operator(Sprite& s, float life, float max) {
(s.*setProp)(func(life, max, elements));
}

// Constructor! And an *initializer list*! omg!
template<typename Iterator>
Tween(FuncType func, propertySetter setProp, Iterator begin, Iterator end) :
func(func), setProp(setProp), elements(begin, end) {}
};

template<class T, typename Iterator>
void Particle::SetTransition(Tween<T>::FuncType tween, Tween<T>::propertySetter setProp, Iterator begin, Iterator end) {
// Look how much shorter! Omg!
tweens.push_back(new Tween(tween, setProp, begin, end));
// initialize property
(*(tweens.back()))(*this, 1.0f, 1.0f);
}


Share this post


Link to post
Share on other sites
Thanks for the replies. I am well aware my code is not as swell as it could be, but I'm still learning and this is some of the most complicated code I've written. I've never dealt with function pointers before.

Anyway, I tried adding your code Zahlman, and received a host of errors.

Quote:

Particle.h(15) : error C2544: expected ')' for operator '()'
Particle.h(23) : see reference to class template instantiation 'Tween<T>' being compiled
Particle.h(15) : error C2146: syntax error : missing ';' before identifier 'Sprite'
Particle.h(15) : error C2182: '()' : illegal use of type 'void'
Particle.h(15) : warning C4518: 'float ' : storage-class or type specifier(s) unexpected here; ignored
Particle.h(15) : warning C4228: nonstandard extension used : qualifiers after comma in declarator list are ignored
Particle.h(15) : warning C4518: 'float ' : storage-class or type specifier(s) unexpected here; ignored
Particle.h(15) : error C2059: syntax error : ')'
Particle.h(15) : warning C4228: nonstandard extension used : qualifiers after comma in declarator list are ignored
Particle.h(15) : error C2143: syntax error : missing ';' before '{'
Particle.h(15) : error C2334: unexpected token(s) preceding '{'; skipping apparent function body
Particle.cpp
Particle.h(15) : error C2544: expected ')' for operator '()'
Particle.h(23) : see reference to class template instantiation 'Tween<T>' being compiled
Particle.h(15) : error C2146: syntax error : missing ';' before identifier 'Sprite'
Particle.h(15) : error C2182: '()' : illegal use of type 'void'
Particle.h(15) : warning C4518: 'float ' : storage-class or type specifier(s) unexpected here; ignored
Particle.h(15) : warning C4228: nonstandard extension used : qualifiers after comma in declarator list are ignored
Particle.h(15) : warning C4518: 'float ' : storage-class or type specifier(s) unexpected here; ignored
Particle.h(15) : error C2059: syntax error : ')'
Particle.h(15) : warning C4228: nonstandard extension used : qualifiers after comma in declarator list are ignored
Particle.h(15) : error C2143: syntax error : missing ';' before '{'
Particle.h(15) : error C2334: unexpected token(s) preceding '{'; skipping apparent function body
Particle.cpp(27) : warning C4346: 'Tween<T>::FuncType' : dependent name is not a type
prefix with 'typename' to indicate a type
Particle.cpp(27) : error C2146: syntax error : missing ')' before identifier 'tween'
Particle.cpp(27) : error C2182: 'SetTransition' : illegal use of type 'void'
Particle.cpp(27) : fatal error C1903: unable to recover from previous error(s); stopping compilation
Mode7.cpp
Particle.h(15) : error C2544: expected ')' for operator '()'
Particle.h(23) : see reference to class template instantiation 'Tween<T>' being compiled
Particle.h(15) : error C2146: syntax error : missing ';' before identifier 'Sprite'
Particle.h(15) : error C2182: '()' : illegal use of type 'void'
Particle.h(15) : warning C4518: 'float ' : storage-class or type specifier(s) unexpected here; ignored
Particle.h(15) : warning C4228: nonstandard extension used : qualifiers after comma in declarator list are ignored
Particle.h(15) : warning C4518: 'float ' : storage-class or type specifier(s) unexpected here; ignored
Particle.h(15) : error C2059: syntax error : ')'
Particle.h(15) : warning C4228: nonstandard extension used : qualifiers after comma in declarator list are ignored
Particle.h(15) : error C2143: syntax error : missing ';' before '{'
Particle.h(15) : error C2334: unexpected token(s) preceding '{'; skipping apparent function body
Mode7.cpp(518) : error C2955: 'Tween' : use of class template requires template argument list
Particle.h(23) : see declaration of 'Tween'
Mode7.cpp(519) : error C2064: term does not evaluate to a function taking 3 arguments


Yeah. I'd tackle these myself but this whole thing is rather confusing to me. The first error it appears to be giving is the () overload. Any thoughts?

Share this post


Link to post
Share on other sites
Typo on zahlman's part. He has


void operator(Sprite& s, float life, float max)


The proper syntax for operator() is

void operator()(Sprite& s, float life, float max)


The rest of the errors appear to be cascading errors off of that.

Share this post


Link to post
Share on other sites
Quote:
Original post by Deyja
Typo on zahlman's part. He has


void operator(Sprite& s, float life, float max)


The proper syntax for operator() is

void operator()(Sprite& s, float life, float max)


Erm, yes. Not sure how I did that :) Well spotted.

Share this post


Link to post
Share on other sites
Yeah, that makes sense. I've done operator overloads, but apparently not enough to catch that.

Anyway, it's closer, but there's still a few errors.

Quote:

Particle.cpp(27) : warning C4346: 'Tween<T>::FuncType' : dependent name is not a type
prefix with 'typename' to indicate a type
Particle.cpp(27) : error C2146: syntax error : missing ')' before identifier 'tween'
Particle.cpp(27) : error C2182: 'SetTransition' : illegal use of type 'void'
Particle.cpp(27) : fatal error C1903: unable to recover from previous error(s); stopping compilation
Mode7.cpp
Mode7.cpp(516) : error C2955: 'Tween' : use of class template requires template argument list
Particle.h(23) : see declaration of 'Tween'
Mode7.cpp(517) : error C3848: expression having type 'Tween' would lose some const-volatile qualifiers in order to call 'void Tween<T>::operator ()(Sprite &,float,float)'


First error refers to this:


void Particle::SetTransition(Tween<T>::FuncType tween, Tween<T>::propertySetter setProp, Iterator begin, Iterator end) {


I prefixed the Tween<T>'s with "typename" as the output said, and it got rid of the warnings, but I wanted to make sure that's what's supposed to be there before I make it permanent. If it's not, stop reading now and let me know.

Anyway, after changing that, these are the remaining errors:

Quote:

Particle.cpp(32) : error C2244: 'SetTransition' : unable to match function definition to an existing declaration
definition
'void Particle::SetTransition(Tween<T>::FuncType,Tween<T>::propertySetter,Iterator,Iterator)'
existing declarations
'void Particle::SetTransition(T (__cdecl *)(float,float,std::vector<T> &),void (__thiscall Sprite::* )(T),T *,int)'
Mode7.cpp
Mode7.cpp(516) : error C2955: 'Tween' : use of class template requires template argument list
Particle.h(23) : see declaration of 'Tween'
Mode7.cpp(517) : error C3848: expression having type 'Tween' would lose some const-volatile qualifiers in order to call 'void Tween<T>::operator ()(Sprite &,float,float)'


I'm not quite sure what to make of those.

Thanks much for the help! We're almost there. :)

Share this post


Link to post
Share on other sites
Have you thought about not using templates? You could, instead, use pure virtual base classes. Assuming I understand your code correctly, instead of using a member function pointer called SetRed, create a virtual base class like this:

class PropertySetter
{
public:
virtual void SetRed (unsigned r) = 0;
virtual void SetGreen (unsigned g) = 0;
virtual void SetBlue (unsigned b) = 0;

protected:
std::vector <Interpolator *>
m_interpolators;
};

and instead of Tween, have a base class:

class Interpolator
{
public:
Interpolate (PropertySetter *ps) : m_ps (ps)
{
}

virtual void Interpolate (float time) = 0;

protected:
PropertySetter
*m_ps;
};

Then, the Sprite class becomes:

class Sprite : public PropertySetter
{
private:
virtual void SetRed (unsigned r) { m_red = r; }
virtual void SetGreen (unsigned g) { m_green = g; }
virtual void SetBlue (unsigned b) { m_blue = b; }
};

Your linear interpolator becomes:

class LinearInterpolator : public Interpolator
{
public:
LinearInterpolator (PropertySetter *ps, float start, float end) :
Interpolator (ps),
m_start (start),
m_end (end)
{
}

private:
virtual void SetChannel (unsigned value) = 0;
virtual void Interpolate (float time)
{
SetChannel (/*interpolate between start/end for time*/);
}
};

class LinearInterpolateRed : public LinearInterpolator
{
public:
LinearInterpolateRed (PropertySetter *ps) : LinearInterpolator (ps)
{
}
private:
virtual void SetChannel (unsigned value)
{
m_ps->SetRed (value);
}
};

And finally, setting the interpolator to the sprite (called from within a sprite member function):

m_interpolators.push_back (new LinearInterpolateRed (this));

Skizz

Share this post


Link to post
Share on other sites
Quote:
Particle.cpp(32) : error C2244: 'SetTransition' : unable to match function definition to an existing declaration
definition
'void Particle::SetTransition(Tween<T>::FuncType,Tween<T>::propertySetter,Iterator,Iterator)'
existing declarations
'void Particle::SetTransition(T (__cdecl *)(float,float,std::vector<T> &),void (__thiscall Sprite::* )(T),T *,int)'
Mode7.cpp
Mode7.cpp(516) : error C2955: 'Tween' : use of class template requires template argument list
Particle.h(23) : see declaration of 'Tween'
Mode7.cpp(517) : error C3848: expression having type 'Tween' would lose some const-volatile qualifiers in order to call 'void Tween<T>::operator ()(Sprite &,float,float)'


In the first error, the last argument type is different. In Particle, you declared it to take an int. In the implementation, you have it taking an iterator. You just copied zahlman's implementation without changing your declaration.

The second error is simple: Somewhere you've used just the identifier 'Tween', without specifying any template arguments.

The third argument is telling you the result of an expression is const Tween<T>, and you are calling operator() on it, but operator() isn't const. Make operator() const. Since it doesn't change the state of Tween, that's fine. (Though it may mean that FuncType has to take that vector argument by const&.)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this