Advertisement Jump to content
Sign in to follow this  
FDsagizi

change memory allocator for CScriptArray addon

This topic is 1784 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

Hi smile.png , in our project - game. We are use only script addon, and we need use Our memory allocator 

and

I create possible to change memory allocator for addon CScriptArray

 

scriptarray.patch

 

 
Index: scriptarray.cpp
===================================================================
--- scriptarray.cpp (revision 1823)
+++ scriptarray.cpp (working copy)
@@ -13,6 +13,14 @@
 static void RegisterScriptArray_Native(asIScriptEngine *engine);
 static void RegisterScriptArray_Generic(asIScriptEngine *engine);
 
+asALLOCFUNC_t CScriptArray::userAlloc = ::malloc;
+asFREEFUNC_t CScriptArray::userFree = ::free;
+
+void CScriptArray::asSetMemoryFunctions(asALLOCFUNC_t allocFunc, asFREEFUNC_t freeFunc){
+ userAlloc = allocFunc;
+ userFree = freeFunc;
+}
+
 struct SArrayBuffer
 {
  asDWORD maxElements;
@@ -36,13 +44,16 @@
 static void CleanupObjectTypeArrayCache(asIObjectType *type)
 {
  SArrayCache *cache = reinterpret_cast<SArrayCache*>(type->GetUserData(ARRAY_CACHE));
- if( cache )
- delete cache;
+ if( cache ){
+    CScriptArray::userFree( cache );
+    cache = nullptr;
+ }
 }
 
 static CScriptArray* ScriptArrayFactory2(asIObjectType *ot, asUINT length)
 {
- CScriptArray *a = new CScriptArray(length, ot);
+ void *data = CScriptArray::userAlloc( sizeof( CScriptArray ) );
+ CScriptArray *a = new( data ) CScriptArray(length, ot);
 
  // It's possible the constructor raised a script exception, in which case we
  // need to free the memory and return null instead, else we get a memory leak.
@@ -58,8 +69,8 @@
 
 static CScriptArray* ScriptArrayListFactory(asIObjectType *ot, void *initList)
 {
- CScriptArray *a = new CScriptArray(ot, initList);
-
+ void *data = CScriptArray::userAlloc( sizeof( CScriptArray ) );
+ CScriptArray *a = new( data ) CScriptArray(ot, initList);
  // It's possible the constructor raised a script exception, in which case we
  // need to free the memory and return null instead, else we get a memory leak.
  asIScriptContext *ctx = asGetActiveContext();
@@ -74,8 +85,8 @@
 
 static CScriptArray* ScriptArrayFactoryDefVal(asIObjectType *ot, asUINT length, void *defVal)
 {
- CScriptArray *a = new CScriptArray(length, defVal, ot);
-
+ void *data = CScriptArray::userAlloc( sizeof( CScriptArray ) );
+ CScriptArray *a = new( data ) CScriptArray(length, defVal, ot);
  // It's possible the constructor raised a script exception, in which case we
  // need to free the memory and return null instead, else we get a memory leak.
  asIScriptContext *ctx = asGetActiveContext();
@@ -268,6 +279,7 @@
  // Same as removeAt
  r = engine->RegisterObjectMethod("array<T>", "void erase(uint)", asMETHOD(CScriptArray, RemoveAt), asCALL_THISCALL); assert( r >= 0 );
 #endif
+
 }
 
 CScriptArray &CScriptArray::operator=(const CScriptArray &other)
@@ -523,11 +535,8 @@
 
  // Allocate memory for the buffer
  SArrayBuffer *newBuffer;
- #if defined(__S3E__) // Marmalade doesn't understand (nothrow)
- newBuffer = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1 + elementSize*maxElements];
- #else
- newBuffer = (SArrayBuffer*)new (nothrow) asBYTE[sizeof(SArrayBuffer)-1 + elementSize*maxElements];
- #endif
+ newBuffer =  (SArrayBuffer*)userAlloc( sizeof(SArrayBuffer)-1 + elementSize*maxElements );
+
  if( newBuffer )
  {
  newBuffer->numElements = buffer->numElements;
@@ -545,8 +554,7 @@
  memcpy(newBuffer->data, buffer->data, buffer->numElements*elementSize);
 
  // Release the old buffer
- delete[] (asBYTE*)buffer;
-
+ userFree( buffer );
  buffer = newBuffer;
 }
 
@@ -584,11 +592,8 @@
  {
  // Allocate memory for the buffer
  SArrayBuffer *newBuffer;
- #if defined(__S3E__) // Marmalade doesn't understand (nothrow)
- newBuffer = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1 + elementSize*(buffer->numElements + delta)];
- #else
- newBuffer = (SArrayBuffer*)new (nothrow) asBYTE[sizeof(SArrayBuffer)-1 + elementSize*(buffer->numElements + delta)];
- #endif
+ newBuffer = (SArrayBuffer*)userAlloc( sizeof(SArrayBuffer)-1 + elementSize*(buffer->numElements + delta) );
+
  if( newBuffer )
  {
  newBuffer->numElements = buffer->numElements + delta;
@@ -614,7 +619,7 @@
  Construct(newBuffer, at, at+delta);
 
  // Release the old buffer
- delete[] (asBYTE*)buffer;
+ userFree( buffer );
 
  buffer = newBuffer;
  }
@@ -752,19 +757,11 @@
 {
  if( subTypeId & asTYPEID_MASK_OBJECT )
  {
- #if defined(__S3E__) // Marmalade doesn't understand (nothrow)
- *buf = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1+sizeof(void*)*numElements];
- #else
- *buf = (SArrayBuffer*)new (nothrow) asBYTE[sizeof(SArrayBuffer)-1+sizeof(void*)*numElements];
- #endif
+ *buf = (SArrayBuffer*)userAlloc( sizeof(SArrayBuffer)-1+sizeof(void*)*numElements );
  }
  else
  {
- #if defined(__S3E__)
- *buf = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1+elementSize*numElements];
- #else
- *buf = (SArrayBuffer*)new (nothrow) asBYTE[sizeof(SArrayBuffer)-1+elementSize*numElements];
- #endif
+ *buf = (SArrayBuffer*)userAlloc( sizeof(SArrayBuffer)-1+elementSize*numElements ); 
  }
 
  if( *buf )
@@ -786,9 +783,8 @@
 void CScriptArray::DeleteBuffer(SArrayBuffer *buf)
 {
  Destruct(buf, 0, buf->numElements);
-
  // Free the buffer
- delete[] (asBYTE*)buf;
+ userFree( buf );
 }
 
 // internal
@@ -1446,7 +1442,9 @@
  }
 
  // Create the cache
- cache = new SArrayCache();
+ void *data = CScriptArray::userAlloc( sizeof( SArrayCache ) );
+ cache = new( data ) SArrayCache();
+
  memset(cache, 0, sizeof(SArrayCache));
 
  // If the sub type is a handle to const, then the methods must be const too
@@ -1569,7 +1567,8 @@
  {
  // When reaching 0 no more references to this instance
  // exists and the object should be destroyed
- delete this;
+ this->~CScriptArray();
+ userFree( (void*)this );
  }
 }
 
Index: scriptarray.h
===================================================================
--- scriptarray.h (revision 1823)
+++ scriptarray.h (working copy)
@@ -25,6 +25,9 @@
 class CScriptArray
 {
 public:
+ static asALLOCFUNC_t userAlloc;
+ static asFREEFUNC_t  userFree;
+ static void asSetMemoryFunctions(asALLOCFUNC_t allocFunc, asFREEFUNC_t freeFunc);
  CScriptArray(asIObjectType *ot, void *initBuf); // Called from script when initialized with list
  CScriptArray(asUINT length, asIObjectType *ot);
  CScriptArray(asUINT length, void *defVal, asIObjectType *ot);
 

 

 

 

 

 

 

Share this post


Link to post
Share on other sites
Advertisement

I upgraded to revision 1855 and hooked up CScriptArray::SetMemoryFunctions() to my debug memory tracking. I'm seeing asymmetric calls to the alloc and release hooks.

 

For example:

 

alloc - ptr returned: 0x0f82cc48

alloc - ptr returned: 0x0f829ac0

 

free - 0x0f82cc48

free - 0x0f829ac0

 

free - 0x0f83cba4 // this did not route through the alloc hook and breaks my debug record keeping

 

I've had my debug tracking running for some time with the engine hooks, for what it's worth, and that's been solid.

 

UPDATE: I think I see what the problem is. Here is where the above 5 calls are coming from:

 

CScriptArray::CreateBuffer()
CScriptArray::Reserve()
 
CScriptArray::Reserve()
CScriptArray::~CScriptArray()
 
CScriptArray::Release() // userFree(const_cast<CScriptArray*>(this));
 
I'm new'ing up a CScriptArray in application code and later I call Release on it, which happens to dealloc the instance, but it's not correct (for my case) to userFree() the this pointer, because the array wasn't allocated via userAlloc() and a placement-new.
 
Since you can't overload placement new in C++, how should this situation be handled?
 
UPDATE2: I added the following to CScriptArray as a test and it worked with the memory hooks:
 
// header
static CScriptArray* MyFactory(asIObjectType *ot);

// cpp
CScriptArray* CScriptArray::MyFactory(asIObjectType *ot)
{
    return ScriptArrayFactory2(ot, asUINT(0));
}

// application C++ code
//CScriptArray* arr = new CScriptArray(0, ot);
CScriptArray* arr = CScriptArray::MyFactory(ot);

This is potentially error-prone though.. at the very least I'd put a huge warning right above CScriptArray::SetMemoryFunctions() ?

Edited by iraxef

Share this post


Link to post
Share on other sites

You're correct. To solve this it is necessary to use Factory functions. To guarantee that the factory functions are always used instead of manually allocating the object, the object constructors should be made protected so they can only be called by the Factory functions.

 

I'll make this change in the CScriptArray object. It will impact those who currently allocate the object manually, but it is for the best in the long run.

Share this post


Link to post
Share on other sites

I've made the changes in revision 1857. Now the CScriptArray should be allocated from the C++ side with a call to CScriptArray::Create(asIObjectType *ot) or one of the other variants.

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!