Advertisement

Access violation in AS engine

Started by June 26, 2012 07:48 AM
2 comments, last by robiwan 12 years, 5 months ago
Ok, so I've successfully setup AS in my project so I can get hold of input arrays, and create output arrays. Or rather, and this is the strange part, I can only create one output array. As soon as I create another one, regardless of whether I use that array, I get an access violation in as_context.cpp (line 2675, AS2.24.0). My script code looks like:

[source lang="cpp"]bool process()
{
const array@ in0 = getInput(0);
uint len0 = in0.length();

array@ out0 = createOutput(0, len0);
array@ out1 = createOutput(1, len0);

print("Hello World! Length = " + len0 + "\n");
for (uint i = 0; i < len0; ++i)
{
print(in0 + "\n");
out0 = -in0;
out1 = in0;
}
return true;
}
[/source]
The C++ array class is as follows:
[source lang="cpp"] class DoubleArray
{
double *m_buffer;
unsigned int m_length;

public:
DoubleArray(double* p, unsigned length) : m_buffer(p), m_length(length) {;}
DoubleArray(const DoubleArray& other) : m_buffer(other.m_buffer), m_length(other.m_length) {;}

void AddRef() const
{
}
void Release() const
{
}

unsigned int length() const
{
return m_length;
}

double at(unsigned int index) const
{
if( index >= m_length )
{
// Raise an exception to the script
asIScriptContext *ctx = asGetActiveContext();
if( ctx )
ctx->SetException("Out of bounds");
return 0;
}

// Return by value as the array shouldn't be modified by the script
return m_buffer[index];
}

double* at(unsigned int index)
{
if( index >= m_length )
{
// Raise an exception to the script
asIScriptContext *ctx = asGetActiveContext();
if( ctx )
ctx->SetException("Out of bounds");
return 0;
}

return m_buffer + index;
}

static void Register(asIScriptEngine* engine)
{
int r = engine->RegisterObjectType("array", 0, asOBJ_REF); assert( r >= 0 );

// The memory management methods
r = engine->RegisterObjectBehaviour("array", asBEHAVE_ADDREF, "void f()", asMETHOD(DoubleArray,AddRef), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASE, "void f()", asMETHOD(DoubleArray,Release), asCALL_THISCALL); assert( r >= 0 );

r = engine->RegisterObjectMethod("array", "double &opIndex(uint)", asMETHODPR(DoubleArray, at, (asUINT), double*), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("array", "double opIndex(uint) const", asMETHODPR(DoubleArray, at, (asUINT) const, double), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("array", "uint length() const", asMETHODPR(DoubleArray, length, () const, asUINT), asCALL_THISCALL); assert( r >= 0 );
}
};
[/source]

And the createOutput function simple creates new DoubleArray(new double[length],length) (and stores it internally in a context object, that's why AddRef/Release aren't implemented). The registering function is:
[source lang="cpp"]engine->RegisterGlobalFunction("array@ createOutput(uint,uint)", asFUNCTION(SContextFunctions::create_output), asCALL_CDECL);

static DoubleArray* create_output(unsigned index, unsigned length)
{
asIScriptContext* ctx = asGetActiveContext();
SContextFunctions* pCtx = (SContextFunctions*)ctx->GetUserData();

if (index > pCtx->outputs.size())
{
ctx->SetException("Outputs must be created in order 0..N");
return NULL;
}
if (index < pCtx->outputs.size())
{
ctx->SetException("Output already created");
return NULL;
}

if (index >= 8)
{
ctx->SetException("Maximum 8 outputs supported");
return NULL;
}

pCtx->outputs.push_back(DoubleArray(new double[length], length));

return &(pCtx->outputs.back());
}
[/source]

The outputs is a std::vector<DoubleArray>.

It is probably something in my code I haven't spotted yet, but I'm pretty confident there's no memory overwrites etc.

Ideas?
Haha! Fixed. Problem was related to push_back on std::vector, which probably reallocated the entries on second push_back. If I just do outputs.reserve(N) then it works like a charm. :)
Advertisement
:)

If you're not planning on using reference counting to manage the lifetime of the arrays you can register the DoubleArray type with the flag asOBJ_NOCOUNT. That way you don't need to register the ADDREF and RELEASE behaviours.

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


If you're not planning on using reference counting to manage the lifetime of the arrays you can register the DoubleArray type with the flag asOBJ_NOCOUNT. That way you don't need to register the ADDREF and RELEASE behaviours.


Okidoki, was searching for something like that :)

This topic is closed to new replies.

Advertisement