Jump to content

  • Log In with Google      Sign In   
  • Create Account


Juliean

Member Since 29 Jun 2010
Offline Last Active Today, 11:26 AM

Topics I've Started

Destructor in vector called too often

Yesterday, 02:29 AM

Hello,

 

I recently experienced a very strange crash, which after inspecting further turned out to be caused by the destructor of a class being called one time too often in a certain vector creation. I havn't been able to fully determine the excact reason this is happening, so I hope some of you guys has a better idea of what could be going on. I'm using VS2013. This is the code that crashes:

const ecs::ComponentDeclaration& Sprite::GenerateDeclaration(void)
{
	const ecs::ComponentDeclaration::AttributeVector vAttributes = 
	{
		{ L"Texture", core::VariableType::STRING, offsetof(Sprite, stTexture), onSetTexture },
		{ L"Blending", core::VariableType::INT, offsetof(Sprite, blend) },
	}; // this line here

	static const ecs::ComponentDeclaration declaration(L"Sprite", vAttributes);

	return declaration;
}

The crash happens in the commented line, so appearently in the vector construction. Let me show you all related code:

struct ACCLIMATE_API ComponentDeclaration
{
public:
	typedef std::vector<AttributeDeclaration> AttributeVector;
		
//...
}

This is the declaration of the vector.

struct ACCLIMATE_API AttributeDeclaration
{
	typedef void(*SetCallback)(BaseComponent& component);

	AttributeDeclaration(const std::wstring& stName, core::VariableType type, size_t offset, SetCallback pCallback = nullptr);

	std::wstring stName;
	size_t offset;
	SetCallback pCallback;
	ICustomComponentAttributes* pCustom;

private:
	core::Variable m_default;
};

AttributeDeclaration::AttributeDeclaration(const std::wstring& stName, core::VariableType type, size_t offset, SetCallback pCallback) :
    stName(stName), pCallback(pCallback), m_default(type, false), pCustom(nullptr)
{
}

Thats the class that is being stored, with all related variables/methods. It stores a core::Variable class, which acts like a semi-variant data-container, which is defined as follows:

class ACCLIMATE_API Variable
{
public:
	static const unsigned int NO_OBJECT = -1;

	Variable(VariableType type, bool isArray);
	Variable(const Variable& variable);
	Variable(Variable&& variable);
	~Variable(void);

	Variable& operator=(const Variable& variable);
	Variable& operator=(Variable&& variable);

private:

	void* m_pData;
	VariableType m_type;
	bool m_isArray;
	unsigned int m_objectType;
};

Variable::Variable(VariableType type, bool isArray) :
	m_type(type), m_isArray(isArray), m_objectType(NO_OBJECT),
	m_pData(nullptr)
{
	ACL_ASSERT(m_type != VariableType::OBJECT);

	if(type != VariableType::UNKNOWN)
		m_pData = CallByTypeNoObject<newData, void*>();
}

Variable::Variable(const Variable& variable) :
	m_type(variable.m_type), m_isArray(variable.m_isArray), m_objectType(variable.m_objectType)
{
	m_pData = CopyData(variable.m_pData);
}

Variable::Variable(Variable&& variable) :
	m_type(variable.m_type), m_isArray(variable.m_isArray), m_objectType(variable.m_objectType)
{
	m_pData = variable.m_pData;

	variable.m_pData = nullptr;
	variable.m_type = VariableType::UNKNOWN;
	variable.m_objectType = NO_OBJECT;
}

Variable::~Variable(void)
{
	// just for simplicities sake - the actual deletion of the correct type is normally handled
	delete m_pData;
}

Variable& Variable::operator=(const Variable& variable)
{
	if(this != &variable)
	{
		m_type = variable.m_type;
		m_isArray = variable.m_isArray;
		m_objectType = variable.m_objectType;

		DeleteData();

		m_pData = CopyData(variable.m_pData);
	}
	
	return *this;
}

Variable& Variable::operator=(Variable&& variable)
{
	if(this != &variable)
	{
		m_type = variable.m_type;
		m_isArray = variable.m_isArray;
		m_objectType = variable.m_objectType;

		m_pData = variable.m_pData;
		variable.m_pData = nullptr;
		variable.m_type = VariableType::UNKNOWN;
		variable.m_objectType = NO_OBJECT;
	}

	return *this;
}

Now the crash happens inside this classes ctor. Obviously, m_pData is destroyed more then once. The call hierachy looks as follows:

 

- ctor of first line is being called (line in the first code snipped)

- ctor for second line is being called

- copy-ctor is called from the object of the first line

- copy-ctor is called from the object of the second line

- Destructor is called on the first object

- Destructor is called on the second object

- Destructor is called on the second object again - crash!

 

Now the reason I know that the destructor is called again, and not m_pData is somehow deleted twice is that by setting m_pData to nullptr in the destructor, the crash resolves. Also note that it is probably not an issue with the Variable-class, as the void* m_pData has already been part of the AttributeDeclaration-class before, as well as part of some other class.

 

_____________________________________________________

 

So, thats about all the information I can give. I can't make any sense of the vector-code, so debugging it further is rather out of the question. My question is now: Does someone see something obviously wrong, or knows/has some idea what is going on? Appearently I *could* fix it by simply putting in the nullptr-set in the ctor, but thats way to hackish and obviously just hides the problem. One thing I find interesting is that the move-ctor isn't called, as it is almost always when dealing with this kind of vector-emplacement, maybe thats related to the problem?

 

 


Passing function template pointer

13 August 2014 - 03:43 PM

Hello,

 

I want to be able to pass a pointer to a templated function as a paramter of another function, without specifying the concret template type. From what I've read, this is not possible per-se, however since my case is very specific, I belive that there is at least a work-around. This is how it should syntactically work and look like:

// template function to be passed & called
template<typename Type>
void appendAttribute(ICustomComponentAttributes::AttributeVector& vAttributes, const xml::Node& value)
{
    vAttributes.emplace_back(value.GetName(), conv::FromString<Type>(value.GetValue()));
}

// this is the receiving function/method
template<typename Function, typename Return, typename... Args> // ???
Return AttributeDeclaration::CallByType(Args&&... args) const
{
    switch(type)
    {
    case AttributeType::BOOL:
        return Function<bool>(args...);
    case AttributeType::FLOAT:
        return Function<float>(args...);
    case AttributeType::INT:
        return Function<int>(args...);
    case AttributeType::STRING:
        return Function<std::wstring>(args...);
    default:
        ACL_ASSERT(false);
    }
}

// in code

attribute.CallByType<appendAttribute>(vAttributes, node);

So as you can see, what I already try is to pass the function as part of a template, which of course didn't work that easily. I searched around a bit and found template template arguments, which unfortunately didn't seem to work for my example.

 

Is there a way to get this to work with a similar way to what I try to achieve with template arguments here? I belive that there is, since technically the template instantiations are known inside the CallByType-method. If there isn't, is there any workaround? Code complexity is of no concern, but it should be as easy to use in the actual code as possible, since this will be used in many instances. Thanks!

 

 

 

 

 

 

 

 


Handling information delivery in editor mode

24 July 2014 - 07:30 AM

Hello,

 

I'm currently working deeply on my editor. As things are starting to get more complex, I often end up in a situation where the amount of, lets call it information handling, of my code is not good enough for some editor features. I have, for example, a visual scripting system, much like the one used in Unreal4. In each such visual script, I can have a number of variables, and like in Unity, all variables marked "public" can be seen and modified from outside. I also have an entity component system, where I have a specific component for attaching a visual script to the entity.

This component should show and allow to modify all public variables. As for this, it currently has a map<string, string>, whose values are written to the visual scripts variables, and also serialized. This is how the class looks:

		class Event :
			public ecs::Component<Event>
		{
		public:

			Event(void);
			Event(const std::wstring& stName);
			~Event(void);

			std::wstring stName;
			core::EventInstance* pInstance;
			std::map<std::wstring, std::wstring> mVariables;

			static const ecs::ComponentDeclaration& GenerateDeclaration(void);
		};

Whenever the name of the visual script (here called "event") is set (thats what the stName-variable is for), the component gets notified via callback and is allowed to query the scripts variables and modify the map accordingly. That part works so far.

 

However, what I don't know how to make work, is what happens when a variable is modified in the visual script. How am I supposed to deliver that information to wherever it is needed in the editor? Don't get me wrong, I know how to transfer such events, via messaging, callbacks, signals... but my question is rather, how I could do this in an efficient and architecturally nice way. The thing is, I don't simply want to add a signal for everything to the class like that:

class EventInstance
{
public:
    
    // ...

    core::Signal<const EventVariable&> SigVariableAdded;
    core::Signal<const std::wstring&> SigVariableRemoved;
    core::Signal<const EventVariable&> SigVariableTypeChanged;

    // ...
}

For the reason being, that I really only every need this for the editor, and the classes here are shared between editor and game. I have a common DLLs that both editor and "player" use, as well as a few plugins that are equally shared. I'm very hasitating to add stuff that is only every needed for that very aspect of "live-feedback" in the editor, which wastes resources and runtime in case of the game, where it is simply not needed. I also don't want to rewrite my classes just for the editor...

 

So what I'm looking for is basically a way to implement such information exchanging for the editor on top of the already existing classes. To put it in a answerable question: How would/did you implement such a thing in an editor? I'm glad for any suggestion, I have a few things in mind, but I don't want to bias anyone. Note that this is just an example, that thing actually happens in a lot of places, so I hope you can help me out without me having to show too much code, but if you need to see something more of the architecture, let me know.


Storing position of member variable

14 July 2014 - 04:23 AM

Hello,

 

I know that there is no such thing like reflection in C++, but I need something a tad bit in that direction. I want to refactor and improve my component system, by automating most loading/serialization/editor-related stuff. For this, I plan on adding a component declaration class, where attributes with a certain known type (int, float, string, ...) are specified. This would look something like that:

class Transform : public ecs::Component<Transform>
{
	math::Vector3 vPosition;
	
	static const ComponentDeclaration& Declaration(void)
	{
		const ComponentDeclaration::AttributeVector vAttributes = 
		{
			{ AttributeType::FLOAT, "x" },
			{ AttributeType::FLOAT, "y" },
			{ AttributeType::FLOAT, "z" },
		}
		
		static const ComponentDeclaration decl(vAttributes);
		
		return decl;
	}
}

Now, I just could have a "serialize/deserialize"-method, but I want to ultimately get rid of those, to minimize work required for each component. Is there any way to calculate/store the "offset" of a member variable and use this to access/set that variable? Something like:

// in the declaration

{ AttributeType::FLOAT, "x", OFFSET(Component::vPosition::x) },

// later on

auto& component = ComponentFactory::CreateComponent(type);

const auto& declaration = component.GetDeclaration();

for(auto& attribute : declaration.GetAttributes())
{
	switch(type)
	{
	case AttributeType::FLOAT:
	{
		float* pAttribute = (float*)(((char*)(void*)(component)) + attribute.offset);
	}
	}
}

How would you do so?

 

PS: Though I don't care about 100% (type)safety and cross-compiler right now, I'm also open for all other, probably better suggestions for that problem you might have.


Refactoring if-conditions for player turn code

10 June 2014 - 01:08 PM

Hello,

 

I've got some code for a 2d game that orients an NPCs graphic towards the direction he is walking to. There are 4 directions (down, left, right, up), that have the values (0, 1, 2, 3) respectively (so 3 - direction will yield the other direction on that axis). It is possible for the NPC to walk straight, diagonally, and unevenly-diagonally (2 pixel on the x-axis, 1 on the y-axis, hope you know what I'm talking about). Now the code for mapping this movement to the direction is rather clumsy, just a big mess of if-statements:

unsigned int DirectionFromMove(const math::Vector2& vMove)
{
	if(vDir.x > 0)
	{
		if(vDir.y > 0)
		{
			if(vDir.x > vDir.y)
				return 2;
			else
				return 0;
		}
		else if(vDir.y < 0)
		{
			if(vDir.x > abs(vDir.y))
				return 2;
			else
				return 3;
		}
		else
			return 2;
	}
	else if(vDir.x < 0)
	{
		if(vDir.y > 0)
		{
			if(abs(vDir.x) > vDir.y)
				return 1;
			else
				return 0;
		}
		else if(vDir.y < 0)
		{
			if(vDir.x < vDir.y)
				return 1;
			else
				return 3;
		}
		else
			return 1;
	}
	else
	{
		if(vDir.y > 0)
			return 3;
		else if(vDir.y < 0)
			return 0;
	}
}

I thought about it for a while, but didn't find any better way myself. I'm really curious, since in "production"-code I always end up with stuff like this. Is there some clever solution here to get rid of all the ifs?


PARTNERS