Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ SMAUG ➜ SMAUG coding ➜ Declared variable not "in current context"

Declared variable not "in current context"

It is now over 60 days since the last post. This thread is closed.     Refresh page


Pages: 1 2  3  

Posted by Darwin   USA  (125 posts)  Bio
Date Sat 05 Apr 2008 10:41 AM (UTC)
Message
I've got an odd problem and I'm not sure what is causing it.

I've created a new skill to tan skins. I have it using add_timer to add a delay, pretty much so that the commands can't be stacked as that would cause the process to stop. Anyway, that part works just fine. When the timer ends and returns to the skill function I have a series of if checks against number_percent to see if the process failed or not.

Pseudo code for those checks looks something like this:
if(number_percent > learned[skill])  // check random number vs learned percent
{
  switch(objvalue) // object state
  {
    case 1: // various "fail" messages
      print "You failed"
      if(number_percent > 85) // chance to ruin/destroy item
        extract_obj(obj)
      return
    case 2:
      print "You failed"
      if(number_percent > 90)
        extract_obj(obj)
      return
    case 3:
      print "You failed"
      if(number_percent > 95)
        extract_obj(obj)
      return
  }
}

Testing this code for several hours, I noticed the skill was failing fairly often, so I raised the values 85, 90 and 95 to 93, 95, 97 respectively. That didn't cause the fail rate to lessen any. This is where the odd part comes in. I added a variable declaration to the top of the function like "int perc = number_percent();" I then replaced all the number_percents in the switch cases with perc so the value wouldn't be different for each case. This didn't change anything. My objects were still getting extracted at an almost 100% rate.

I ran this through gdb to check the value of the variable. I set a break point on the function and went to test it. The break point was reached so I checked the current values of all the variables in the function with "info locals" All of the variables showed up except for the "perc" variable I added. Doing a "list" showed that it was there and declared. I tried "p perc" but gdb just gives the response 'No symbol "perc" in current context.'

That didn't help. I changed the if checks within the switch to read <= 7, 5, 3 and declared perc as "int perc = 10;" Even that didn't change anything. The skill still failed and destroyed the object every time, even though 10 is clearly not less than 7, 5 or 3.

So, why is this variable not showing up in the scope of this function?
Top

Posted by Robert Powell   Australia  (367 posts)  Bio
Date Reply #1 on Sat 05 Apr 2008 01:26 PM (UTC)
Message
I think you would need to show the actual function, to me it sounds more like a logic error where your doing something after the block you have shown that changes everything, but without seeing the code its impossible to tell.


Just a guy having a bit of fun. Nothing more, nothing less, I do not need I WIN to feel validated.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #2 on Sat 05 Apr 2008 08:35 PM (UTC)
Message
I agree it would help to see the function. I would also add a default case handler, eg.


case 3:
      print "You failed"
      if(number_percent > 95)
        extract_obj(obj)
      return

default:
      print "Unexpected objvalue";
      return;

  }


Anyway, the code you posted doesn't look like C to me. I don't see how it will compile. Just looking at part of it, this:


case 3:
      print "You failed"
      if(number_percent > 95)
        extract_obj(obj)
      return
  }


Should have 3 more semicolons and some brackets, like this:


case 3:
      print ("You failed");
      if(number_percent > 95)
        extract_obj(obj);
      return;
  }


Oh, I see, you said pseudo-code. Well again, it will help to see the actual code.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Darwin   USA  (125 posts)  Bio
Date Reply #3 on Sat 05 Apr 2008 11:01 PM (UTC)
Message
Well, it turns out I did have an error. They were semicolons on the ends of my if lines. Anyway, that still didn't fix the problem as the variable wasn't showing up as in the context of the function.

I'm not sure how it could be a logic problem. The variable, no matter what it was, was not showing up, according to gdb, as being in the context of the function. I tried declaring it with no value, then declaring it with a value. In both cases the variable's value could not be checked as it wasn't showing up in the function context.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #4 on Sun 06 Apr 2008 12:24 AM (UTC)
Message
Well, once again, it is hard to debug your logic, or the way you are using gdb, without showing us any of your code.

At least show the function and the place where you are declaring this variable, with a few lines around them. One thing that springs to mind is that it is optimized away. Did you suppress optimization?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Darwin   USA  (125 posts)  Bio
Date Reply #5 on Sun 06 Apr 2008 01:57 AM (UTC)

Amended on Sun 06 Apr 2008 02:00 AM (UTC) by Darwin

Message
This is the only part of the function that uses the variable.
void do_tan( CHAR_DATA *ch, char *argument )
{
	OBJ_DATA *skin;
	char buf[MAX_STRING_LENGTH];
	char arg1[MAX_STRING_LENGTH];
        int perc;

	if(IS_NPC(ch))
	{
		send_to_char("&WHuh?\n\r", ch);
		return;
	}

	if ( ch->pcdata->learned[gsn_tan] == 0 )
	{
		send_to_char( "You don't know how to do that... yet.\n\r", ch);
		return;
	}
...
	if ( (number_percent() > UMAX(ch->pcdata->learned[gsn_tan], 20)  ) && !IS_IMMORTAL(ch))
	{
                perc = 10;
		switch(skin->value[0])
		{
			case 1:
				ch_printf(ch, "&WYou fail to use enough salts to cover %s.\n\r&D", skin->short_descr);
				if(perc <= 7)
				{
					ch_printf(ch, "&RThe lack of salt has destroyed your %s.&D\n\r", myobj(skin->short_descr));
					extract_obj(skin);
				}
				break;
			case 2:
				ch_printf(ch, "&WYou miss large sections of the skin while removing the flesh and fat.\n\r&D");
				if(perc <= 5)
				{
					ch_printf(ch, "&R%s has begun to decay.&D\n\r", capitalize(skin->short_descr));
					extract_obj(skin);
				}
				break;
			case 3:
				ch_printf(ch, "&WYou clumsily spill your tanning oils.\n\r&D");
				if(perc <= 3)
				{
					ch_printf(ch, "&R%s has hardened and become useless.\n\r&D", capitalize(skin->short_descr));
					extract_obj(skin);
				}
				break;
		}

Output from gdb
Breakpoint 1, do_tan (ch=0x1a3a5d0, argument=0x5bfca9 "") at skills.c:8472
8472    {
(gdb) info locals
skin = <value optimized out>
buf = "$n arrives from the west.\000\000.\000.\0005:49 2008 :: House of Ghouls \020\000\000\000&#65533;g\002\001\000\000\000\000v&#65533;P\000\000\000\000\000\033[0m&w[&zSat Apr  5 05:46:18 2008&W]\n\r&w<&R1361&w/&r1618 &B1205&w/&b1847 &G1436&w/&g1436 &Y698562&Wgp (&C-2507491&W) &Go"...
arg1 = "&#65533;&#65533;N;&#65533;\177\000\000}&#65533;&#65533;\001\000\000\000\000&#1061;&#65533;\001\000\000\000\000&#1061;&#65533;\001", '\0' <repeats 12 times>, "G&#65533;Q\000\000\000\000\000&#1061;&#65533;\001\000\000\000\000\235&#65533;E\000\000\000\000\000\030\000\000\0000\000\000\000&#65533;&#65533;N;&#65533;\177\000\000Sat Apr  5 05:46:18 2008\000&#65533;&#65533;\001\000\000\000\000tan\000lcome to House of Ghouls...\n\r\000\000\000\000\000\000\0001", '\0' <repeats 15 times>, "\v&#65533;&#65533;ox+\000\000\001\000\000\000\000\000\000\000&#65533;&#65533;N;&#65533;\177\000\000\fDX\000\000\000\000\000\rDX\000\000\000\000"...
(gdb) n
8478            if(IS_NPC(ch))
(gdb) n
8484            if ( ch->pcdata->learned[gsn_tan] == 0 )
(gdb) n
8490            switch( ch->substate )
(gdb) n
8539                    if ( !ch->alloc_ptr )
(gdb) n
8545                    strcpy( arg1, ch->alloc_ptr );
(gdb) n
8546                    DISPOSE( ch->alloc_ptr );
(gdb) n
8555            skin = get_obj_carry(ch, arg1);
(gdb) n
8556            separate_obj(skin);
(gdb) n
8558            if ( (number_percent() > UMAX(ch->pcdata->learned[gsn_tan], 20)  ) && !IS_IMMORTAL(ch))
(gdb) n
8560                    perc = 10;
(gdb) p perc
No symbol "perc" in current context.
Top

Posted by Darwin   USA  (125 posts)  Bio
Date Reply #6 on Sun 06 Apr 2008 02:17 AM (UTC)
Message
I tried various things like changing the variable to "percent" and "i" and various other things, just to make sure there wasn't some conflict with the variable name... not likely to be the case, but I checked anyway. In all cases the variable was not in context each time I tried checking the value.

After removing the *cough* misplaced semicolons on the ends of my if statements, I went back to using number_percent() and removed the whole variable mess. So it works like I had planned it to work.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #7 on Sun 06 Apr 2008 03:53 AM (UTC)
Message
I asked "Did you suppress optimization?" to which you didn't reply.

I notice:


skin = <value optimized out>


I suggest debugging with optimization turned off. The variable may not yet have been created.


(gdb) n
8560                    perc = 10;
(gdb) p perc
No symbol "perc" in current context.


At that point the line "perc = 10;" has not yet been executed. Try one line further on. Also try without optimization.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #8 on Sun 06 Apr 2008 03:59 AM (UTC)
Message
With optimization on the compiler is likely to move things around, that is what optimization is about. It is hard to debug with optimization on. Also it may do things like simply store a calculation like "perc = 10" into a CPU register and not a variable, is it sees it is only used in a couple of places.

My page about using gdb, which is http://www.gammon.com.au/forum/?id=3653 suggests turning optimization off.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Darwin   USA  (125 posts)  Bio
Date Reply #9 on Sun 06 Apr 2008 04:07 AM (UTC)
Message
Quote:
I asked "Did you suppress optimization?" to which you didn't reply.

Oh, sorry. I saw the question and completely forgot about it while I was writing my reply. I haven't changed any of the options in the makefile except for removing .c and .h files that I no longer need due to having removed snippetized features from the source. I believe that optimization is enabled in the compile flags. I'm not entirely sure what exactly that does for the executable in terms of debugging, compiled size or speed.

Here's the line from my Makefile
C_FLAGS = $(OPT_FLAG) -O -g3 -Wall -Wuninitialized $(PROF) $(NOCRYPT) $(DBUGFLG) -DSMAUG $(SOLARIS_FLAG) $(TIME) $(REG)


What does the optimization do?
Is it something that I should keep or leave it alone?
Top

Posted by Darwin   USA  (125 posts)  Bio
Date Reply #10 on Sun 06 Apr 2008 04:11 AM (UTC)
Message
Quote:
At that point the line "perc = 10;" has not yet been executed. Try one line further on.

The responce was the same no matter when I tried to print the value. I had initialized the variable in it's declaration at the top of the function and when that line was reached, it still gave the same "not in current context" responce. Even checking at the end of the function, it still said the same thing.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #11 on Sun 06 Apr 2008 05:32 AM (UTC)

Amended on Sun 06 Apr 2008 05:34 AM (UTC) by Nick Gammon

Message
Quote:

What does the optimization do?


Well you can optimize for speed, size, both or neither. Optimizing for speed may cause some functions to be "inlined" which means that rather than calling a function, it reproduces it inline. This can make the executable larger. Optimizing for size may do the opposite, and try to find places where you do things more than once, and do them more efficiently. Optimizing for both tries to reduce both execution time and program size.

In any case, optimized code can be hard to debug because the compiler has moved things around from what you see in the source code. See this note from the gcc manual page (my emphasis):

Quote:

Unlike most other C compilers, GCC allows you to use -g with -O. The shortcuts taken by optimized code may occasionally produce surprising results: some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; some statements may not be executed because they compute constant results or their values were already at hand; some statements may execute in different places because they were moved out of loops.


Note the comment about variables not existing. :)

Now this is the description of the -O option, which you used (again, my emphasis):

Quote:

-O

Optimize. Optimizing compilation takes somewhat more time, and a lot more memory for a large function.

Without -O, the compiler’s goal is to reduce the cost of compilation and to make debugging produce the expected results. Statements are independent: if you stop the program with a breakpoint between statements, you can then assign a new value to any variable or change the program counter to any other statement in the function and get exactly the results you would expect from the source code.

With -O, the compiler tries to reduce code size and execution time, without performing any optimizations that take a great deal of compilation time.


You have used -O in the (Makefile) line you posted, although I repeatedly suggested you turn optimization off. Unless you do that, posting problems about variables not existing is not much use. Make sure you do a "make clean" afterwards to force a recompilation.

Note that it says that optimization takes time - that is the drawback, plus the problems with debugging. The plus side is your code may run slightly faster (if you optimize).

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Darwin   USA  (125 posts)  Bio
Date Reply #12 on Sun 06 Apr 2008 06:00 AM (UTC)
Message
Ah, you are a wealth of information, Nick.

I have taken your advice and removed the -O flag. I know you had suggested it before, but honestly, I didn't realize that it was optimized. Like I said, I just left all those flags the way they were when I inherited it.

I did notice that compiling didn't take as long as it had before. Also, the executable seems to be a little smaller than it was before, even with a bunch of new code added to it.

I'm not sure that optimizing for speed would yield any noticeable differences. I'll play around with it for a while and check it out.

On a side note, I have two versions of the code: one that I build on at home, and the other that is running live on a hosted site. What would your opinion be about leaving optimization on at the live version and off on my home version? Would that be ok, or would you still suggest turning optimization off there as well?
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #13 on Sun 06 Apr 2008 06:32 AM (UTC)
Message
I don't think a MUD server is a particularly CPU-intensive application, as for most of the time it is waiting for player input. Thus I don't think optimization will help a lot.

OTOH, if it ever crashes, it will be easier to debug from the core file if you have it turned off, so I would leave it off.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #14 on Sun 06 Apr 2008 06:39 AM (UTC)
Message
It would be interesting to have you confirm that, if you remove the -O option, and recompile everything, your problem with "not in current context" goes away.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


87,544 views.

This is page 1, subject is 3 pages long: 1 2  3  [Next page]

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.