Problems with inserting Struct data into Vector

Started by
5 comments, last by NotAYakk 16 years, 11 months ago
I'm having difficulties inserting Struct data into Vector. What I'm trying to do, is to insert Particle structs to vector inside Particle class, but I'm getting weird errors: Particle.obj : error LNK2001: unresolved external symbol __imp___CrtDbgReportW fatal error LNK1120: 1 unresolved externals The errors didn't tell anything on what line the error were. Here is some code if it helps: Particle.h


#pragma once

#include "Texture.h"

#include <string>
#include <iostream>
#include <vector>
using namespace std;

struct Particle
{
	float x, y;
	float velX, velY;
	float alpha;
};

class CParticle
{
public:
	CParticle( int x1, int x2, int y1, int y2, int amount, string texturePath );

	

	void UpdateParticles( float deltaTime );
	void DrawParticles();

	void SetX1(int x) { m_nCoordX1 = x; }
	void SetX2(int x) { m_nCoordX1 = x; }

	void SetY1(int y) { m_nCoordY1 = y; }
	void SetY2(int y) { m_nCoordY2 = y; }

public:
	~CParticle( void );

private:
	Particle CreateParticle();
	
	vector <Particle> m_particleList;    // <- here is where i'd like to store Particle structs
	CTexture* m_particleTexture;	

	int m_nAmount;
	int m_nCoordX1;
	int m_nCoordY1;
	int m_nCoordX2;
	int m_nCoordY2;
};



Particle.cpp


#include "Particle.h"

CParticle::CParticle( int x1, int x2, int y1, int y2, int amount, string texturePath )
{
	m_particleTexture = new CTexture( texturePath.c_str() );

	m_nCoordX1 = x1;
	m_nCoordY1 = y1;
	m_nCoordX2 = x2;
	m_nCoordY2 = y2;

	m_nAmount = amount;

	for (int i = 0; i < m_nAmount; i++)
	{
		m_particleList.push_back( CreateParticle() );   // Here I insert the new particles to vector
	}	
}

CParticle::~CParticle(void)
{
	delete m_particleList;
}

Particle CParticle::CreateParticle()
{
	Particle particle;

	srand( (unsigned)time( NULL ) );

	particle.x = (float)((rand() % 130) + 5);
	particle.y = (float)((rand() % 130) + 5);

	particle.velX = (float)(rand() % 20) - 10.0f;
	particle.velY = (float)-(rand() % 30) - 20.0f;

	particle.alpha = (rand() % 100) / 100.0f;
	
	return particle;
}

void CParticle::UpdateParticles( float deltaTime )
{	
}

void CParticle::DrawParticles()
{
}



Advertisement
Quote:
delete m_particleList;

How does this even compile?

Also, you fail to delete m_particleTexture.
Call srand() only once in your program, at the start of main() is best.
Why not store the texture by value, and not via a pointer:

class CParticle{public:	CParticle( int x1, int x2, int y1, int y2, int amount, string texturePath );	void UpdateParticles( float deltaTime );	void DrawParticles();	void SetX1(int x) { m_nCoordX1 = x; }	void SetX2(int x) { m_nCoordX1 = x; }	void SetY1(int y) { m_nCoordY1 = y; }	void SetY2(int y) { m_nCoordY2 = y; }        // the default destructor suffices now	// ~CParticle( void );private:	Particle CreateParticle();		vector <Particle> m_particleList;	CTexture m_particleTexture;	        // this isnt needed, use m_particleList.size() instead	//int m_nAmount;	int m_nCoordX1;	int m_nCoordY1;	int m_nCoordX2;	int m_nCoordY2;};CParticle::CParticle( int x1, int x2, int y1, int y2, int amount, string texturePath ):     m_particleTexture(texturePath.c_str()),     m_nCoordX1(x1),     m_nCoordY1(y1),     m_nCoordX2(x2),     m_nCoordY2(y2){	for (int i = 0; i < m_nAmount; i++)	{		m_particleList.push_back( CreateParticle() );   // Here I insert the new particles to vector	}	}

We could also move the code for CreateParticle into a constructor for particles.

This would simplfy more of the code:
struct Particle{        Particle(); 	float x, y;	float velX, velY;	float alpha;};Particle::Particle(){        // these could be moved to initialiser lists too        // but I dislike big expressions in initialiser lists...        x = (float)((rand() % 130) + 5);	y = (float)((rand() % 130) + 5);	velX = (float)(rand() % 20) - 10.0f;	velY = (float)-(rand() % 30) - 20.0f;	alpha = (rand() % 100) / 100.0f;}// class CParticle is the same, except take out CreateParticle()CParticle::CParticle( int x1, int x2, int y1, int y2, int amount, string texturePath ):     m_particleList(amount),     m_particleTexture(texturePath.c_str()),     m_nCoordX1(x1),     m_nCoordY1(y1),     m_nCoordX2(x2),     m_nCoordY2(y2){}


Finally you may have noted that none of this seems to be addressing the CrtDbgReport link error [smile]. You'd be right, as that is (AFAIK) a VC++ specific thing and I don't use VC++. Hopefully someone else can help you with that.
It might have something to do with some object files being compiled as unicode, and others without, resulting in missing functions (they'd get linked, but wrong names).

It might be that there's a mix up between release and debug configs, or between statically linked and dynamic runtime libraries.

The error you're getting has nothing to do with your code as such. It means that some of the runtime libraries aren't linking properly. Do a clean rebuild first. Then check that your project doesn't have inconsistent settings.

But your code (whether it compiles or not) has nothing to do with it. That function is simply part of debug libraries used in (I think) memory leak/overrun detection.
Thanks for your help, but I still didn't get it to work... [rolleyes]

I made few changes for the code, but now I'm having these errors:
Particle.obj : error LNK2019: unresolved external symbol "public: __thiscall Particle::Particle(void)" (??0Particle@@QAE@XZ) referenced in function "private: struct Particle __thiscall CParticle::CreateParticle(void)" (?CreateParticle@CParticle@@AAE?AUParticle@@XZ)

Particle.obj : error LNK2019: unresolved external symbol __imp___CrtDbgReportW referenced in function "public: struct Particle & __thiscall std::vector<struct Particle,class std::allocator<struct Particle> >::operator[](unsigned int)" (??A?$vector@UParticle@@V?$allocator@UParticle@@@std@@@std@@QAEAAUParticle@@I@Z)

C:\Documents and Settings\Petri\Desktop\Matopeli_OpenGL\Debug\Matopeli.exe : fatal error LNK1120: 2 unresolved externals

Particle.h
#pragma once#include <time.h>	// For random number generation#include "Texture.h"#include <string>#include <iostream>#include <vector>using namespace std;struct Particle{	float x, y;	float velX, velY;	float alpha;};class CParticle{public:	CParticle( int xMin, int xMax, int yMin, int yMax, int amount, string texturePath );	void UpdateParticles( float deltaTime );	void DrawParticles();	void SetMinX(int x) { m_nCoordMinX = x; }	void SetMaxX(int x) { m_nCoordMaxX = x; }	void SetMinY(int y) { m_nCoordMinY = y; }	void SetMaxY(int y) { m_nCoordMaxY = y; }public:	~CParticle( void );private:	Particle CreateParticle();		vector <Particle> m_particleList;	CTexture *m_particleTexture;		int m_nCoordMinX;	int m_nCoordMinY;	int m_nCoordMaxX;	int m_nCoordMaxY;};



Particle.cpp
#include "Particle.h"CParticle::CParticle( int xMin, int xMax, int yMin, int yMax, int amount, string texturePath ):    m_nCoordMinX(xMin),    m_nCoordMinY(yMin),    m_nCoordMaxX(xMax),    m_nCoordMaxY(yMax){	m_particleTexture = new CTexture( texturePath.c_str() );	for (int i = 0; i < amount; i++ )	{		m_particleList.push_back( CreateParticle() );	}}CParticle::~CParticle(void){}Particle CParticle::CreateParticle(){	Particle particle;		particle.x = (float)((rand() % m_nCoordMaxX - m_nCoordMinX) + m_nCoordMinX);	particle.y = (float)((rand() % m_nCoordMaxY - m_nCoordMinY) + m_nCoordMinY);	particle.velX = (float)(rand() % 30) - 20.0f;	particle.velY = (float)-(rand() % 30) - 20.0f;	particle.alpha = (rand() % 100) / 100.0f;		return particle;}void CParticle::UpdateParticles( float deltaTime ){		for (int i = 0; i < m_particleList.size(); i++)	{		// Update position		float newX = m_particleList.x + m_particleList.velX * deltaTime;		float newY = m_particleList.y + m_particleList.velY * deltaTime;		m_particleList.x = newX;		m_particleList.y = newY;		// Update velocity (add gravity)		m_particleList.velY += 200.0f * deltaTime;		// Update alpha		float newAlpha = m_particleList.alpha - deltaTime/1.0f;		m_particleList.alpha = newAlpha;		// Check if out		if (newY > 480 || newAlpha <= 0.0f)		{			m_particleList = CreateParticle();		}	}}void CParticle::DrawParticles(){	for (int i = 0; i < m_particleList.size(); i++)	{		SDL_Rect rect;		rect.x = (int)m_particleList.x;		rect.y = (int)m_particleList.y;		rect.w = 64;		rect.h = 64;		glColor4f(1.0f, 1.0f, 1.0f, m_particleList.alpha);		m_particleTexture->draw(rect);	}}



Hmm... there's something wrong with pasting code here, some plus -marks are not showing.
If you're getting those errors and its not from your code, try these:

1. Properties -> C/C++ -> General -> Additional Include Directories: alleg.lib (or whatever additional library you're using)
2. Properties -> C/C++ -> Code Generation -> Runtime Library: Multi-threaded DLL (/MD)
3. Properties -> Linker -> Input -> Additional Dependencies: alleg.lib (same deal as step 1)
4. Properties -> Manifest Tool -> General -> Use FAT32 Work-around: Yes
5. Properties -> Manifest Tool -> Input and Output -> Embed Manifest: No

Assuming you're using VC++. Also, try re-compiling after each step so you know which solves your problem.
Still getting those errors. [sad]
So, can you read error messages?

Look at this one:
Quote:Particle.obj : error LNK2019: unresolved external symbol "public: __thiscall Particle::Particle(void)" (??0Particle@@QAE@XZ) referenced in function "private: struct Particle __thiscall CParticle::CreateParticle(void)" (?CreateParticle@CParticle@@AAE?AUParticle@@XZ)


It says "I tried to look for an empty Particle constructor. I couldn't find it anywhere".

Sort of a strange error, because your struct Particle; is POD (plain old data).

The first thing I'd do is stop polluting the global namespace. I have no clue what garbage is in the global namespace from other libraries.

So place your code in your own namespace.

The second thing I'd do is stop using "using namespace std", or any "using namespace" commands. Doing it in a header file means you deserve any and all compiler bugs.

Import the symbols you need via using std::vector, or by typedef std::vector<blah> blah_vec. This is a matter of code sanitation.

The third thing I'd do is stop using #pragma once, and start using #ifdef header guards. In fact, I find this useful:

#pragma once#ifndef HeaderGuard#define HeaderGuard...#else#pragma warning ("#pragma once failed in " __FILE__)#endif


The possibility of multiple versions of the same header file existing can cause more bugs than you could ever dream possible. #pragma once is a poor guard against that eventuality.

Next, we have a chunk of code that isn't working. It is pretty self contained -- it uses CTexture and a few helper functions.

Move the self-contained part of the project into it's own project. Get it working all alone in a sane environment. Once that happens, move it back.

Because once you have it working in a sane environment, you can be sure that your problem is your environment, not your source code.

Alternatively, reduce your code down to the point where you have a minimal test-case that produces the bug. Then try to reproduce the bug in a slightly different way.

Good luck, and may the fish you catch be tasty.

This topic is closed to new replies.

Advertisement