Null Pointer referenced with char.ActiveInventory.Nam

Started by demophobie, Fri 05/10/2007 03:25:48

Previous topic - Next topic

demophobie

hi ppl!

I need help. I checked the Manual, but i could not find the reason for the error message:
"Null pointer referenced" "run_text_script1:error -6 running function repeatedly_execute"
here my script:

function repeatedly_execute()
  {
  string console, buffer;
  int cur_mode,  mode;
  mode = GetGlobalInt(299);
  cur_mode = GetCursorMode();
  StrCopy (console, "");
 
  if (cur_mode == 0) StrCat(console,"Gehe zu ");
  else if (cur_mode == 1) StrCat (console, "Schau an ");
  else if (cur_mode == 2 && cMarty.ActiveInventory.Name != null) {
    StrCat(console, "Gib ");
    StrCat(console, cMarty.ActiveInventory.Name);
    StrCat(console, " an ");
  }


  GetLocationName(mouse.x, mouse.y, buffer);
   StrCat(console, buffer);
   SetLabelText (0, 0, console);
   
    }

The error appears, when i click on button 2.

I'm a newbie. Plz dont be too hard to me ;)

Gilbert

#1
I supposed you're using V2.7+ right?

In that case, try not to use the obsolete old string type and functions like StrCat(), especially when cMarty.ActiveInventory.Name is now declared as the new String type (note the capitalisation), putting it as an argument for an old string function like StrCat() might not work.

I'd tried fixing your script (not tested):

function repeatedly_execute()
  {
  String console, buffer;
  int cur_mode,  mode;
  mode = GetGlobalInt(299);
  cur_mode = mouse.Mode ;
  console = "";
 
  if (cur_mode == 0) StrCat(console,"Gehe zu ");
  else if (cur_mode == 1) console = console.Append("Schau an ");
  else if (cur_mode == 2 && cMarty.ActiveInventory.Name != "") {
   console = console.Append("Gib");
   console = console.Append("cMarty.ActiveInventory.Name");
   console = console.Append("an");
  }


  buffer=Game.GetLocationName(mouse.x, mouse.y);
           lblTemp.Text = console.Append(buffer);
           //Substitute lblText with the correct script name for the lable 0 of GUI 0
   
    }

Edited: Tried to convert more into the new OO-style scripting.

monkey0506

Actually (I believe) the reason it wasn't working would be that cMarty.ActiveInventory is null (i.e., Marty has no active inventory item), hence the "null pointer reference" error. Also, Gilbot, instead of appending the active inventory item's name, you simply appended the text "cMarty.ActiveInventory.Name".

function repeatedly_execute()
  {
  String console;
  int cur_mode = mouse.Mode,  mode = GetGlobalInt(299);
 
  if (cur_mode == 0) console = "Gehe zu ";
  else if (cur_mode == 1) console = "Schau an ";
  else if ((cur_mode == 2) && (cMarty.ActiveInventory != null) && (cMarty.ActiveInventory.Name != null)) {
    console = "Gib ";
    console = console.Append(cMarty.ActiveInventory.Name);
    console = console.Append(" an ");

    // or more simply: console = String.Format("Gib %s an " cMarty.ActiveInventory.Name);
  }
 
  if (gui[0].Controls[0].AsLabel != null) gui[0].Controls[0].AsLabel.Text = console.Append(Game.GetLocationName(mouse.x, mouse.y));
  // or use the script o-name as Gilbot suggested such as: lblConsole.Text = console.Append(Game.GetLocationName(mouse.x, mouse.y));
    }

Gilbert

#3
Quote from: monkey_05_06 on Fri 05/10/2007 04:30:14
Actually (I believe) the reason it wasn't working would be that cMarty.ActiveInventory is null (i.e., Marty has no active inventory item), hence the "null pointer reference" error.
Yeah thanks, didn't notice that.

Quote
Also, Gilbot, instead of appending the active inventory item's name, you simply appended the text "cMarty.ActiveInventory.Name".
I don't quite get it, can you elaborate? Nevermind, got it.

Actually I think checking a String is "" is the same as checking if it's null now (correct me if I'm wrong, as I'm using the V2.6 branch and am not really familiar with the modern OO versions), so you don't really need to check if it's null in the last Append line (moreover, isn't it the POINT to give the label content when it's empty?).

monkey0506

Quote from: Gilbot V7000a on Fri 05/10/2007 05:02:32Actually I think checking a String is "" is the same as checking if it's null now

Nope. An empty string-literal ("") and a null String pointer are not the same thing. It'd be nice...but not currently the case. Which can lead to a lot of confusion between null Strings and "".

Quote from: Gilbot V7000a on Fri 05/10/2007 05:02:32(moreover, isn't it the POINT to give the label content when it's empty?)

Not sure what you mean here. As long as GUI 0's first GUIControl is a label then its text will always be set. If mouse.Mode is not 0, 1, or 2 then, granted, no cursor mode would appear before the location name; but his original code would have done that. The location name will always be appended (even if it is an empty string-literal).

Gilbert

Quote from: monkey_05_06 on Fri 05/10/2007 05:20:08
Nope. An empty string-literal ("") and a null String pointer are not the same thing. It'd be nice...but not currently the case. Which can lead to a lot of confusion between null Strings and "".
Right-o, just checked, they are different...

QuoteNot sure what you mean here. As long as GUI 0's first GUIControl is a label then its text will always be set. If mouse.Mode is not 0, 1, or 2 then, granted, no cursor mode would appear before the location name; but his original code would have done that. The location name will always be appended (even if it is an empty string-literal).
In that case, there's not even a point to include "if (gui[0].Controls[0].AsLabel != null)". If it's not a gui label, just an ordinary String, this check is even more troblesome, as you're telling it not to assign anything to the String when it has nothing, which is rarely the case.

monkey0506

If what's not a label? A GUIControl can't be a String. I'm telling it not to assign anything to what String? And what are you saying has "nothing"? And why would it be rarely the case for that thing to have nothing? ???

Gilbert

I couldn't understand, if gui[0].Control[0] is written there then that GUIControl was supposed to be a label already (unless there's a mistake, or if you are routinely setting things with a while loop, then you need to reject the non-labels), so why the check? :P

If it's not a GUIControl, just a String, the case is even clearer. It's rare that when you are assigning content to a String, you don't want to do so if that String is a null String.

So I am just saying that if your konw that when something can be viewed as a String, it's really rare to need to do the following (unless it's really intended in some cases):
if (something!=null) something="blah";

monkey0506

#8
But the difference is that I was testing if the AsLabel property of the GUIControl was null. A GUIControl can be represented as any of the GUIControl types: Button, Label, TextBox, InvWindow, etc. You can check if a GUIControl is one of these types using the GUIControl.AsX properties. If the GUIControl isn't of type X then the property will be null.

So if the GUIControl is a Label (which we can assume it probably is) then we can access the AsLabel property without any fear. However, in the event that it is not a Label, the AsLabel property will be null. Attempting to access the Text property of the AsLabel property would then fail with a null pointer reference....

By ensuring that the AsLabel property of the GUIControl is not null, I prevent possible game crashes due to null pointer references. Is this a problem for you?

I haven't done:

if (something != null) something = "blah";

I've done:

if (something != null) something.Property = "blah";

Surely you can recognize the difference.

It's no different than the need to check that the Character.ActiveInventory property is non-null before attempting to access its Name property (the original problem).

Gilbert

#9
If gui[0].Control[0] is not a label then it never is (unless it's changed in the editor), so the line is useless anyway. If you can specifically write gui[0].Control[0] there you should know what you're doing already.

By the something part I already said that something was assumed as String, so if it was a property of some certain structure something would itself mean structure.somestring already.

The discussion is beginning to drift out of the scope of the original question, I think I will split the thread if it goes on like this. :P

monkey0506

Feel free to split if if you find it necessary. If you're using gui[0].Controls[0] then you probably should know what you're doing. But realistically would it be better to allow the game to crash with an error message meaning nothing to you ("null pointer referenced") instead of just throwing up alarms by not working the way you expect?

Quote from: Gilbot V7000a on Fri 05/10/2007 09:27:03By the something part I already said that something was assumed as String, so if it was a property of some certain structure something would itself mean structure.somestring already.

As for this...again...I wasn't testing if the String was null...I was testing if the Label* was null to prevent errors. I wasn't testing the value of a pointer before setting the pointer. I was testing the value of a pointer before attempting to access any of its properties.

It would be easier and safer to use the script o-name of the label. My only intention in going with the GUI.Controls route was to provide a more exact translation of the existing code. Once he becomes more familiar with 2.71+ and how to set up script o-names and the like, then it would be easier and safer to use that instead. But for purposes of translating the 2.62- code to 2.71+ code, I used this method.

Gilbert

Quote from: monkey_05_06 on Fri 05/10/2007 09:56:28
But realistically would it be better to allow the game to crash with an error message meaning nothing to you ("null pointer referenced") instead of just throwing up alarms by not working the way you expect?
I don't think so, really, if realistically it was to check for error, I agree that it can be something like
Code: ags

if (blah != null) do something;
  else Display("something wrong here, check the codes!");

first for debugging purposes, but once it's tested and you are certain you are correct you can always remove the unnecessily debugging bits.
Quote
As for this...again...I wasn't testing if the String was null...I was testing if the Label* was null to prevent errors. I wasn't testing the value of a pointer before setting the pointer. I was testing the value of a pointer before attempting to access any of its properties.
I think you have missed the point here, by the something part I had mentioned in the very beginning I was not initially referring to the property of a structure (specifically, a GUIControl in this case), it was extra information that if we're just dealing with an ordinary String, there's little point to check if it's null when we want to assign something to it.

demophobie

Hey !

Thanks for the fast help!

it works for me now and i finally understood this "null pointer" mistake  :-*

here the code:

function repeatedly_execute()
  {
   
  String  console, buffer;
  int cur_mode = mouse.Mode;
 
  if (cur_mode == 0) console ="Gehe zu ";
  else if (cur_mode == 1) console ="Schau an ";
  else if (cur_mode == 2) console = "Gib ";
  else if ((cur_mode == 4) && (cMarty.ActiveInventory != null) && (cMarty.ActiveInventory.Name != null))
    {
    console = "Gib ";
    console = console.Append(cMarty.ActiveInventory.Name);
    console = console.Append(" an ");
    }
 
  if (Game.GetLocationName(mouse.x, mouse.y) != "")
  buffer = Game.GetLocationName(mouse.x, mouse.y);
   else
  buffer = "";
 
  console = console.Append(buffer);
  SetLabelText (0, 0, console);
   
  }

Now i have to solve the problem, that the character can't give an inventory item to the item itself ;-)
But i will check out the manual - i have to learn this stuff.
btw: is there a translation of the manual on german?

Patrick

SMF spam blocked by CleanTalk