String Issues

Started by
8 comments, last by WitchLord 19 years, 4 months ago
I have am having a few issues getting strings to work as well as I would like them to. I am defining the string functions as follows (does it matter if they are not static functions?)

CScriptString StringFactory(asUINT _length, const char* _s)
{
	CScriptString string;

	// Set the string
	string.SetString(_s, _length);
	// Return the object
	return string;
};

void ConstructString(CScriptString* _thisPointer)
{
	_thisPointer = new CScriptString;
}

void DestructString(CScriptString* _thisPointer)
{
	_thisPointer->~CScriptString();
}

CScriptString& AssignString(CScriptString& _other, CScriptString& _thisPointer)
{
	return _thisPointer = _other;
}

CScriptManager::asEngine->RegisterObjectType ("string", sizeof(CScriptString), asOBJ_CLASS_CDA);
CScriptManager::asEngine->RegisterStringFactory("string", asFUNCTION(StringFactory), asCALL_CDECL);
CScriptManager::asEngine->RegisterObjectBehaviour ("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructString), asCALL_CDECL_OBJLAST);
CScriptManager::asEngine->RegisterObjectBehaviour ("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructString), asCALL_CDECL_OBJLAST);
CScriptManager::asEngine->RegisterObjectBehaviour ("string", asBEHAVE_ASSIGNMENT, "string &f(const string&)", asFUNCTION(AssignString), asCALL_CDECL_OBJLAST);
I am having two problems with this as the moment The first is that I am getting a memory leak from the variable created in ConstructString. I read an other post which suggested that the construction functions should be:

void ConstructString(CString &self)
{
  new(&self) CString;
}
but if i apply this the compiler conplains about the code inside the (). I am overridding new for my memory manager, would this be a problem? The second problem is if I allocate the char array within my CScriptString class as and when it is needed instead of just giving it a default size from the start. If i new the char array, and then store the string in there, then the string i get out of the script is trashed, whareas if I make it a fixed length, there is no problem. I have made sure that my allocation code copies the string, so its not as if it is only passing a pointer then trashing that... Hope some one can give me a few pointers on how to fix this Oh, and the script i am running is simply:

string = "Hello World";
Thanks in advance Spree
Advertisement
No, it doesn't matter if the functions are static or not. For global functions the static keyword only tells the linker which modules can see the functions or not. It doesn't change anything else.

Your only problem is the ConstructString() function. You really have to use the form: new(p) CScriptString(). This is because the memory for the string has already been allocated by the script engine, the function just needs to initialize it. If you allocate a new string the original memory won't be initialized, and the new string won't be known by the library as you have no way of passing it back to the library.

void ConstructString(CScriptString* _thisPointer){	new(_thisPointer) CScriptString;}


If the compiler complains about the placement new operator, then you need to include <new.h> that declares this operator. I don't know If this will work with your custom memory manager. If it doesn't then you'll have to implement your own placement new operator.

The problem you're having with the static/dynamic memory thing is most likely because of the error with your ConstructString() function that doesn't initialize the memory the library is using.

You may also want to take a look at stdstring.h/stdstring.cpp that registers the std::string class for use with the library.

Hope that helps.

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

OK, thansk for the advice. Ill look into altering my new operator so it can handle the way in which it needs to be called.

For now, I can just have a static length string, instead of allocating the space as it is needed, bacuse I can easily get it to work that way

Thanks
Spree
IIRC; overiding new for a class disables use of placement new, unless placement new is also explicitly supplied. There is, however, very little you can do in placement new. The new operator is meant only to allocate memory. Placement new cannot do even this, as the memory is already allocated and supplied to it. AFAIK, the global placement new operator looks something like this: void* new(void* ptr, size_t) { return ptr; } Of course, it can still be used as a hook for memory tracking code.

Also, your construct string should take a pointer, not a reference, and don't use leading underscores in identifiers. Such names are reserved for use by the compiler and standard library.
I actually got around the problem by having Construct(...) and Destruct(...) functions, which are called in the ConstructString and DestructString functions accordingly. This negates the need to use the placement new. This method seems to be working absolutly fine, though I am unsure if it will work if I start to use more complicated class (but I'm hoping to avoid that, and make the CScriptString class the most complicated class i use).

As for the underscore, I've never had any problems with this, and I have used this method for years. Granted it might cause problems occasionally in the future, but as its my own code, I have no problem with that :)

Spree
Using special methods Construct/Destruct to initialize the members of the object will work as long as the object don't use virtual fuctions or multiple/virtual inheritance.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

They should use any of the advance features. Im purposfully keeping my scrip/object code simple, and avoiding anything that might make the code a tad complicated to understadn until i know more about what im doing

Spree
That technigue is potentially deadly if the class contains any members that need constructed. In such a case, you can either design all the members to not need their constructor called, or go back and call the constructor in the first place.

I really would like to know why you can't just use placement new.
Quote:Original post by Deyja
That technigue is potentially deadly if the class contains any members that need constructed. In such a case, you can either design all the members to not need their constructor called, or go back and call the constructor in the first place.


Since the only place im going to be using the more complicated features of AngelScript would be with the string class, this shouldnt be a problem. As i mentioned above, I'm trying to keep it simple for now so I dont get my knickers in a twist.


Quote:Original post by Deyja
I really would like to know why you can't just use placement new


All my memory allocation is done using my memory code, which obviously over-rides new and delete. This means I get a ton of errors if I #include <new.h>.

I did over ride new so it supported placement new (new(...) { return (_ptr); } I cant remeber the extact code at the mo). This seemd to be the only way I could do override it so it supported the placement new syntax.

As far as I could see, this did nothing. It just returned the memory pointer, meaning that still nothign was created. The method I have now, while now perfect I will admit that, does the job I want it to do, which at the end of the day is all I ask of it:)

Spree
As far as I know the placement new isn't supposed to do any more than return the same pointer that it received. It could be used for logging the allocation though.

The object constructor is called automatically by the compiler using the pointer that the new operator returned. Since it is not possible to call the constructor explicitly you have to use the placement new to make the compiler call the constructor to initialize the memory allocated by AngelScript.

So if you already have the placement new operator working for your memory manager so that it returns the same pointer that it receives this should work very well for initializing the objects.

Give it a try and see if it works.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement