Jump to content
  • Advertisement

Overloaded operator results in null pointer exception when result isn't stored in variable

Recommended Posts

Best to describe with some code.

This works:

vec3 diff = s.getPosition() - capturePosition;
float length = length2(diff);
And this throws null pointer exception (Null pointer access):
float length = length2(s.getPosition() - capturePosition);
"vec3" is registered type with overloaded operator "-". Is there any reason why it shouldn't work without storing result in variable?
vec3 is registered as (leaving out unrelated stuff)
engine->RegisterObjectType("vec3", sizeof(Vec3Primitive), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CDAK);

engine->RegisterObjectBehaviour("vec3", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(vec3Constructor), asCALL_CDECL_OBJLAST);

engine->RegisterObjectBehaviour("vec3", asBEHAVE_CONSTRUCT, "void f(float,float,float)", asFUNCTION(vec3Constructor3), asCALL_CDECL_OBJLAST);
engine->RegisterObjectBehaviour("vec3", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(vec3Destructor), asCALL_CDECL_OBJLAST);

engine->RegisterObjectMethod("vec3", "vec3 opSub(const vec3)", asMETHOD(Vec3Primitive,opSub), asCALL_THISCALL);

engine->RegisterGlobalFunction("float length(const vec3)", asFUNCTION(Vec3Primitive::length), asCALL_CDECL);
void vec3Constructor(void *memory){
    new(memory) Vec3Primitive();

void vec3Constructor3(float x, float y, float z, void *memory){
    new(memory) Vec3Primitive(x, y, z);

void vec3Destructor(void *memory){

static float length2(const Vec3Primitive vec3){
   return vec3.x * vec3.x + vec3.y * vec3.y + vec3.z * vec3.z;

Vec3Primitive opSub(const Vec3Primitive other){
    return Vec3Primitive(x - other.x, y - other.y, z - other.z);
I'm using AngelScript version 2.31.1
I've registered this class some time ago and just now added operator overloading, which brought this error. Maybe I am doing something obviously wrong?

Share this post

Link to post
Share on other sites

Did you also register the copy constructor and assignment operator? You specified these as being present (asOBJ_APP_CLASS_CDAK) but you didn't show them. You may be having issues there.


Also, you showed the registration for length but not length2, could you show the code for that?

Share this post

Link to post
Share on other sites

I thought asOBJ_POD takes care or assignment and copies. Or doesn't it mix with asOBJ_APP_CLASS_CDAK? I'll definitely try adding copy constructor and assign op to see if it helps. Is there a reason why it would work when passing variable to lenght2, but not when passing opSub result directly?

length vs length2 - I just me copied wrong line, but they are only differ in function body (sqrt)

Share this post

Link to post
Share on other sites

Hi valenn,

this has the looks of being a bug in the AngelScript compiler. There shouldn't be any need to store the result of opSub in a variable before passing it on to the next function. I'll investigate it. 

You didn't say where the null pointer exception is coming from? 



Just a couple of tips (not necessarily related to the bug):

- Instead of using the flags asOBJ_APP_CLASS_CDAK, use the asGetTypeTraits function. That way you don't have to guess what flags to use, e.g. asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<Vec3Primitive>().

- Does your Vec3Primitive really have an explicit destructor that does anything? If not, I suggest skipping the registration of the destructor behaviour. That would be one less call that the script engine has to do.

- Your length() and length2() functions are taking the argument by value. I suggest changing it to take it as const reference (i.e. const vec2 &in). This will allow the compiler to skip making a copy of the vector in some situations, thus improving the efficiency. 

Share this post

Link to post
Share on other sites

Null pointer is coming from asBC_COPY (as_context.cpp, in ExecuteNext()). Simply adding copy constructor as suggested by Solokiller solved the issue for me. (thanks!)

r = engine->RegisterObjectBehaviour("vec3", asBEHAVE_CONSTRUCT, "void f(const vec3 &in)", asFUNCTION(vec3ConstructorCopy), asCALL_CDECL_OBJLAST); assert( r >= 0 );

void vec3ConstructorCopy(const Vec3Primitive &in, void *memory){
    new(memory) Vec3Primitive(in);

Assignment works as expected (making a copy) even without registering copy constructor or assignment operator. If this is indeed bug, and not only missing copy constructor, let me know if I can help somehow

Thank you also for other tips!

Edited by valenn
forgot formatting of code

Share this post

Link to post
Share on other sites

Registering the copy constructor will work-around the problem, but it shouldn't be necessary. It is surely a bug in 2.31.1 that is causing this null pointer exception.


I haven't been able to reproduce this problem with the latest WIP version from the svn yet. The version you are using is nearly one and a half year old. Would you mind giving the latest WIP version a try to see if you can reproduce the problem in that?


float length = length2(s.getPosition() - capturePosition);


In this code, can you tell me what s is? and how it was declared? Is it a script class? registered type? Is it a global variable, or a local variable?

What is the signature of the method getPosition()? Does it return the vec3 by value or by reference?

The capturePosition variable? is it global, local, or a function argument?



Share this post

Link to post
Share on other sites

I'll try with latest version and let you know.

"s" in previous example is registered type, "getPosition()" returns vec3 by value and "capturePosition" is a member variable of script class. But that probably won't matter, because now I also reproduced it with:

vec3 a = vec3(1.0, 1.0, 1.0);
vec3 b = vec3(0.0, 0.0, 0.0);
float l = length2(b - a);


float l = length2(vec3(1.0, 1.0, 1.0) - vec3(0.0, 0.0, 0.0));


Share this post

Link to post
Share on other sites
5 hours ago, valenn said:

vec3 a = vec3(1.0, 1.0, 1.0); vec3 b = vec3(0.0, 0.0, 0.0); float l = length2(b - a);

This was the first I tried when attempting to reproduce the problem. 

I'm pretty sure this bug has already been fixed in the latest WIP version. 

Looking through the change log for throughout the year can see a couple of fixes that may very well have fixed this problem.


Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!