QB64.org Forum
Active Forums => QB64 Discussion => Topic started by: MasterGy on May 27, 2021, 05:22:46 am
-
Hello ! when the program stops with an error message, it also tells you which queue the error is on. If I stop the program, it will exit the program. Is there any .log, large log file where qb records which line the program was on when I stopped it?
This would be very good if it could be read from somewhere, because in an infinite loop it would be easier to find the location of the error.
-
it might be possible to hide it in the exe compiler, so that if you stop the program while pressing, for example, the shift or some "secret button", a window would say goodbye to which queue the program was on when you exited.
-
Write yourself a small routine to error trap your code.
ON ERROR GOTO DebugLine 'can't use GOSUB
ERROR 250 'simulated error code
END
DebugLine:
PRINT _ERRORLINE
RESUME NEXT ‘Or END, if you want the program to close on error
-
the problem is not that simple. for such cases I use it within a cycle
do ..... print # 1, X .... loop
vagy
do .... print timer, X .... loop
from these I see a value within a cycle and also whether it changes (timer)
There is a large program. The game. It runs nicely for minutes and then stops. It always triggers the same thing. But without an error message. So it doesn't break, it stops. exits ctrl + break .... so I think it's running .... . There are a lot of loops working in it and I will check back one by one, but how good it would be if you write ctrl + break somewhere, at which row, at which operation it was aborted. What’s the point of putting in the ERROR 250 if I know where I put it? On this basis I could write ERROR1, ERROR2, ERROR3 after each instruction .....
-
I'm not sure you understood Steve's suggestion but another thing you could do is open a console and echo the variable values you want to track. Or, you can write to a text file periodically in your loop and when the program ends you can inspect the last line and see what value the variables were when it failed.
-
Yeah I like Spriggsy's suggestion, use console as 2nd window to report program data.
I had same problem in Pool program. It was hanging on breaks because of infinite loops (I thought vector code couldn't handle overlapping balls so I misdiagnosed problem), no errors are thrown so nothing to catch but the program just runs and runs and gets nowhere.
So if you print to console every time you loop some special loop ID you can see where you are getting stuck but this idea will really slow down execution so it is act of extreme desperation ;-))
What I did was printed an line ID before and after points in program and traced it down to where line x wasn't getting to line x + 1 say in top left corner of screen, you will see last line ID point that gets executed. Again slows the program execution way down and to be used only as extreme act of desperation.
Just make 2 points and move them closer and closer together until you isolate the bad section.
-
I managed to find the error.
But from that the question is still given. Because of the example, I made a BAS generation program to understand what I want :)
I'm looking for a mistake just like you. DE! What about this ?
Suppose I change one of the conditions and it does not exit the cycle.
Wouldn’t it be nice to know which line you’re on when we stop?
-
don't avoid the question! if I stop the program and get which queue you went to, it’s a huge help in many cases!
-
Good grief that looks like way too much
-
Here, as I was saying above -- just write your own error handler:
I used your example and tossed a simulated error in there at some random point, and this seems to do the job for me on finding it easily enough. Are you certain something like this won't work for your needs?
-
But @SMcNeill you need an error thrown! In an infinite loop no errors get thrown. Am I missing something?
I say either:
1: print out all x(i) (and why not use an array MasterGy?) in console window and see which one isn't going anywhere
or
2: print loop id number before and after the loop(s) and narrow down the problem loop.
print (to console?) enter loop IdX
do(s)
print enter loop IdY
do(s)
loops
print exit loop IdY
loop(s)
print exit loop IdX
for nested loops start in deepest nest and work your way out until you don't get an exit message.
-
SMcNeil, and if the infinite cycle does not occur at 89? we are there. then in the worst case I have to place "error 5" in 100 places and try again? Instead of "error 5" we can also do "print" HERE I AM ".... this does not solve the infinite loop error finding.
-
If you're talking about storing the line number for when you decide to manually close a program, you'd want to use _EXIT and ON TIMER to create a custom exit loop, along with a variable to store the line numbers you want to track.
t1 = FREETIMER
PRINT "You manually exited the program on line #"; ln
All endless loops. This would normally lock a program up forever more, but you can use the nice big red X in the top right corner to exit and end the program at any time -- and when you do so, it'll tell you the line that it was on when you exited the program..
-
yes Bplus, do you understand what I mean!
-
Wow ! i like this _EXIT command, i didn't know it before! De! you still avoided the question! You made 5 cycles and identified each one. I intentionally showed 100 cycles. then I put an ID in front of all a hundred? If I did, it would be enough to print the ID with an "on key".
-
yes Bplus, do you understand what I mean!
I think I do, but Steve's last looks better than my ideas so far, specially for the monster you show LOL!
-
Wow ! i like this _EXIT command, i didn't know it before! De! you still avoided the question! You made 5 cycles and identified each one. I intentionally showed 100 cycles. then I put an ID in front of all a hundred? If I did, it would be enough to print the ID with an "on key".
Even better!
-
Wow ! i like this _EXIT command, i didn't know it before! De! you still avoided the question! You made 5 cycles and identified each one. I intentionally showed 100 cycles. then I put an ID in front of all a hundred? If I did, it would be enough to print the ID with an "on key".
As far as I know, there's no _LINENUMBER command built into QB64, so there's no way to get that value back natively without generating your own ID. If you're going with 100 loops, and glitch out in them, then you might want to try Felippe's debugger (which basically adds the labels before compiling your code automatically), or else just add them yourself.
-
You keep saying he's avoiding the question but I don't see that being the case. Perhaps you aren't explaining your problem clearly? I would think you are saying that your program is crashing to desktop rather than failing with a message box alert, correct?
-
As far as I know, there's no _LINENUMBER command built into QB64, so there's no way to get that value back natively without generating your own ID. If you're going with 100 loops, and glitch out in them, then you might want to try Felippe's debugger (which basically adds the labels before compiling your code automatically), or else just add them yourself.
You can use a preprocessor macro in a header to generate a static count. Each time the function is called it is increased by 1. That could be helpful, perhaps. Perhaps not.
-
Aha the Interpreter advantage, press a key and piece of cake to tell what line number you're on and what all the variables are looking like at that moment! And stepping through code, and setting break points... all that good ole stuff!
-
Thank you for your answers. the torment remains. Due to the lack of a simple thing about which queue to stop running when we exit.
-
yes Bplus, it helped a lot, for example such a problem was solved in an instant. I remember under DOS :) Unfortunately, it takes 1 day for a 160kbyte program to see where this kind of error is.
-
I don’t think you’ll ever find simple answers with 100 loops stacked.
Do
Do
Do
Do
Do....
Now, let’s say the 2nd loop is the endless loop... if we manually exit, or hit a key at any time (such as ON KEY), WHY would we do it inside loop 2? Why couldn’t the program be in loop 3, 4, 5+ when we exit? Those loops all run fine; it’s not until we get to loop 2 that we endlessly repeat. Just having a line number by itself doesn’t help much, or at least, I don’t see how it could.
-
Aha the Interpreter advantage, press a key and piece of cake to tell what line number you're on and what all the variables are looking like at that moment! And stepping through code, and setting break points... all that good ole stuff!
https://www.qb64.org/forum/index.php?topic=458.0 — That’s the closest to all that ole stuff that you’re going to come.
-
Bplus, anyway i am very happy with the QB64! if it weren’t for it, I wouldn’t be able to implement my ideas so quickly, efficiently. In the old days, unfortunately, because of speed, I was forced to give up a lot of things. This shortcoming is a trifle. In the next version, I will suggest that if ctrl + break exits, if you also press SHIFT, for example, a window will say goodbye, which will print out which queue the processing took. I think that would solve the infinite-cycle problem.
-
SMcNeil, suppose I give you a program. huge size. be 10Mbyte and one day it would be read. I secretly place a "DO: LOOP" in it. You are sure that the program will not run due to an endless cycle. My suggestion would solve this problem in an instant. Otherwise, it may take 1 week to find the error.
-
@MasterGy couldn't you check your loops from the inside out with that key press thing (as opposed to exit) you could see if entering and exiting innermost, then check next innermost... keep going until you find the bad one?
I am talking about a method electricians use to track down a bad component or circuit.
The inner most loop is what has to pass to get to next item in 2nd inner most loop...
-
Thanks, SMcNeill, I'm going to try this!
-
Thanks Bplus for the idea! I already found the error. It took a few hours. But if I know which line you’re stuck with, I’ll win a couple of hours. So the problem remains. It could help anyone at any time if we at least knew where the program was going. All this without loading the source code just for debugging.
-
If I understand correctly...
The problem relates to where you were in a program when you prematurely terminate a running program (because of say an infinite loop).
Things can get "messy" because QB64 is a compiled based environment. In the old days (some 30 years ago) this type of problem was addressed by using an interpreter based BASIC (eg MS PDS 7.1 which was an upgrade to QB45). I do not know of QB45 (never used it) but with PDS 7.1 one could do all development work in the interpretive environment (break a program at predetermined point, on condition, etc and examine variable information). Because of the p-threading nature (I think) of PDS 7.1 it was practically almost as fast as a stand alone .exe which you could also easily create. So the .exe did not really need special condition checking or fancy error code settings in the program, as in the development/debug stage (using the interpretive environment) one would have hopefully sorted out all the possible bugs. QB64 effectively only works by development testing of the compiled exe.
I have previously suggested that QB64 go along the path of interpretive based (like PDS 7.1) and a few other forum members also support this. However there are forum members (including developers it seems) that are opposed to interpretive based version of QB64. So thirty years ago it was "less painful" to develop, debug and test a BASIC program, and when working, one would create the .exe file then.
In many ways, I still prefer using PDS 7.1 over QB64, because of what mentioned above - but obviously because of hardware improvements over the past 30 years, PDS 7.1 is very limited.
-
https://www.qb64.org/forum/index.php?topic=458.0 — That’s the closest to all that ole stuff that you’re going to come.
oh?
-
yes Richard, your suggestion is very good! You wouldn't even need an interpreter here! When we run the exe and press ctrl + break, the exit occurs. I’m sure something stores the line. (I think if there is an error, you know). This should just be printed out!
-
if it were in qb 7.1 _MAPTRIANGLE and I would also use it because of the things listed :)
-
Just a bit of a detour...
To attempt to take advantage of all QB64 features and still have superior features from the past (PDS 7.1) - I experimented having a "dual environment" (for want of a better term) for my development work. Basically it involved the following...
Generate the QB64 program as usual (running as first instance of QB64).
Open up a second instance of QB64 ( and say have a red IDE background).
The second instance of QB64 has a program to read your first instance program and does some modifications to a copy of your program such as inserting line labels (which are exactly the line numbers you see in the IDE of the first instance i.e. your program under development). Also can insert all sorts of things like program breakpoints, display eg on the title bar or console window, disk file, etc, etc of variables, relative timings, history, events. Effectively the second instance of QB64 has a "bloated" version of your original program, it will run much slower, simultaneously display/save all the variables you choose, etc. By automatically inserting (in the second instance) a "universally used subroutine" - you could single step (forward or backward) or branch elsewhere.
Once the "bloated" program (QB64 instance #2) is setup, run this to debug. Because the line labels correspond to your original program (QB64 instance #1), it is easy to find where to edit as necessary the original program.
A big disadvantage of my approach is that if you edit the "bloated" program ie to make it work, your original program will not be updated. The idea of dual instances of QB64 accessing the exact same program/file with automatic updating of the IDE was rejected - was advised to use say NotePad instead of the second instance.
-
It sounds like you are suggesting to use vWatch, which is a program made by Fellippe for debugging QB64 programs :)
-
Well, here's one way to do it:
Enable debug symbols under Options -> Advanced
Compile your program. Here's mine:
Print "hello"
While 1
Print "world"
For i = 1 To 10
Print i
Next i
Wend
Launch the program under gdb and run it:
$ gdb untitled
Reading symbols from untitled...done.
(gdb) run
When you think your program is stuck, kill it with ^C and switch to thread 2:^C
Thread 1 "untitled" received signal SIGINT, Interrupt.
0x00007ffff7d3ebf0 in __GI___nanosleep (
requested_time=0xb56c10 <Sleep(unsigned int)::ts>, remaining=0x0)
at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28 ../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory.
(gdb) thread 2
Get a stack trace:(gdb) bt
#0 __GI___printf_fp_l (fp=fp@entry=0x7ffff55c0bc0, loc=<optimized out>,
info=info@entry=0x7ffff55c0720, args=args@entry=0x7ffff55c0700)
at printf_fp.c:1246
#1 0x00007ffff788f7c9 in ___printf_fp (fp=fp@entry=0x7ffff55c0bc0,
info=info@entry=0x7ffff55c0720, args=args@entry=0x7ffff55c0700)
at printf_fp.c:1267
#2 0x00007ffff788a54b in _IO_vfprintf_internal (s=s@entry=0x7ffff55c0bc0,
format=format@entry=0x4cde7d "% .6E", ap=ap@entry=0x7ffff55c0cf0)
at vfprintf.c:1637
#3 0x00007ffff78ac321 in __IO_vsprintf (
string=0xb48640 <qbs_str_buffer> " 1.000000E+000", format=0x4cde7d "% .6E",
args=args@entry=0x7ffff55c0cf0) at iovsprintf.c:42
#4 0x00007ffff7892774 in __sprintf (s=<optimized out>, format=<optimized out>)
at sprintf.c:32
#5 0x0000000000449876 in qbs_str (value=10) at libqb.cpp:6893
#6 0x00000000004095e7 in QBMAIN (unused=0x0) at ../temp/main.txt:47
#7 0x00000000004091fb in QBMAIN_LINUX (unused=0x0) at qbx.cpp:2084
#8 0x00007ffff7d34fa3 in start_thread (arg=<optimized out>)
at pthread_create.c:486
#9 0x00007ffff79334cf in clone ()
at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Note QBMAIN is at temp/main.txt line 47, so open internal/temp/main.txt and look at line 47:
45 do{
46 tqbs=qbs_new(0,0);
47 qbs_set(tqbs,qbs_add(qbs_str((float)(*__SINGLE_I)),qbs_new_txt(" ")));
48 if (new_error) goto skip6;
49 makefit(tqbs);
50 qbs_print(tqbs,0);
51 qbs_print(nothingstring,1);
52 skip6:
53 qbs_free(tqbs);
54 qbs_cleanup(qbs_tmp_base,0);
55 if(!qbevent)break;evnt(6);}while(r);
Line 55 is a code fragment that is generated after every BASIC line (more or less). The call to evnt(6) indicates that the preceeding code, including line 47, corresponds to line 6 in the BASIC source.
-
thanks Luke, this is an interesting approach! I will study. interesting thing is what else to see with it.