Debugger error 193 lazarus - windows

I can't debug one of my programs for a year now. When I press the green Run button, the following error message appears:
The full text is:
The GDB command:
"-exec-run"
returned the error:
",msg="Error creating process C:/Users/leven/OneDrive/J\341t\351kpogramok/People/people.exe, (error 193).""
I've read many forums about this error, but my case looks a bit different...
As you can see, the file's path doesn't include any characters that could occur this problem (no spaces, no special letters). I've tried running outside OneDrive, same error.
I've spent a lot of time looking for something in my program that occurs this error and found that if I delete some parts of it (eg. a few procedures or functions, which contains a lot of code though), the program is debuggable again! So the trouble is with some parts of the program, but I still don't know the exact problem.
As I can remember, I've always debugged this program in a 64bit OP.
The one thing that could be problematic is that I probably started writing the program using Windows 7 or 8, and now I want to run it using Windows 10, but I still don't understand, why deleting some parts of the program is a solution...
Thanks in advance for your help!
UPDATE:
I've found, that the line
p[x,y,2,1]:=r;
cannot be debugged by the compiler.
Description:
p: array [1..15000, 1..10000, 1..7, 1..4] of integer;
p[] is a game field. The first two parameters are coordinates, the third and the fourth are not important.
x, y and r are integers.
So, the command seen above writes a number into the game field (p[]) array using the x, y coordinates.

I think we established through a series of queries in comments that the necessary and sufficient condition to provoke the debugger problem you've been getting is to include in your app the declaration of the array p that you've added to your q, that is:
var
p: array [1..15000, 1..10000, 1..7, 1..4] of integer;
For you, it seems that just including this declaration in your code is sufficient to make the debugger throw the error you quote.
For me the debugger starts fine but I get a SIGSEGV error on the assignment to p[] in the following code:
var
p: array [1..15000, 1..10000, 1..7, 1..4] of integer;
x,
y,
r : integer;
begin
x := 100;
y := 100;
r := 666;
p[x, y, 1, 1] := r;
writeln('Press any key ...');
readln;
end.
So, I would try smaller values for the first two bounds of the p array. If that works and you still need the original bounds, I would suggest looking for an FPC library which implements "sparse arrays" and declare p as one of those.
Good luck!

Related

Small numbers misrepresented in windows

I am running a model which is written in Fortan (an executable), in some runs it started to deliver constant errors and apparently incoherent results, however when I closely checked the results file (a text with n columns of data) and I realized that when the concentration of certain mineral is very very low, lets say 2.9984199E-306, the code omits the 'E' and the number presented is 2.9984199-306 which of course causes problems. Since I have no access to the source code of the executable file, is there a way to avoid this problem in Windows? I have seen that in other computers these numbers are directly replaced by zero, however I was not able to find the specific configuration to achieve it.
You will need access to code to change the output formatting or you will need to post-process your output. You are seeing standard conforming Fortran behavior. Consider the simple program
program foo
implicit none
real(8) x
integer i
x = 1
do i = 1, 10
x = x / 5.4321e11
write(*,'(ES15.7)') x
end do
end program foo
It's output is
1.8409086E-12
3.3889446E-24
6.2387373E-36
1.1484945E-47
2.1142735E-59
3.8921843E-71
7.1651557E-83
1.3190397E-94
2.4282316-106
4.4701525-118
See Fortran 2018 Standard, 13.7.2.3.3 E and D editing, in particular, Table 13.1.

My program bounces back and forth between for and if, I have no idea why

I'm doing some homework and there's this problem where I have to make a program that tells me how many prime numbers there are between two numbers given by the user. For some reason, when I test the program with F8 I can see the program bounces back and forth between "for" and "if", for no apparent reason. And yes, I HAVE to use this language.
I have tried restanting the IDE, hoping it'ts just some bug (like it often happens on Android Studio). I don't know what else to try, this is the first time I use Lazarus and PASCAL.
program PrimoEntre;
var
a, b, i, q: Integer;
begin
write('Ingrese el primer valor: ');
readln(a);
write('Ingrese el segundo valor: ');
readln(b);
for i:=a to b do //It starts bouncing back and forth from here...
begin
q:=2;
if((b>=2)AND(b<=10)) then //...to here.
begin
while((q>=2) and (q<=b)) do
begin
if(a<>b) then
begin
if((a MOD b)=0) then
begin;
//i ES NO PRIMO
if(q=b) then
begin
writeln('No existen numeros primos entre ', a, ' y ', b, '.');
end;
q:=(q+1);
end;
end
else
begin
if(q=b) then
begin
//i ES PRIMO
writeln(i, ' es primo.');;
q:=1
end;
end;
end;
end
else
begin
while((q>=2) and (b<=10)) do
begin
if(a<>b) then
begin
if((a MOD b)=0) then
begin
//i ES NO PRIMO
if(q=b) then
begin
writeln('No existen numeros primos entre ', a, ' y ', b, '.');
end;
q:=(q+1);
end;
end
else
begin
if(q=b) then
begin
//i ES PRIMO
writeln(i, ' es primo.');
q:=1
end
end;
end;
end;
end;
readln();
end.
I expect the output to be one of the following:
-The console writing every time it finds a prime number between a and b.
-The console saying there isn't any prime number between a and b.
Instead, there's no result. The program just gets stuck and I have to terminate it manually.
You say you are trying to find prime numbers in the range a...b. The problem is that
you are doing this in a quite unnecessarily complicated way and the main reason
your program is jumping all over the place is that you are making it do so because
you are making the value of your q variable jump all over the place.
What I think you should do it to slow down and think what you are trying to do:
You want to iterate the integers in the range a to b. Your for loop does
this fine, with the value of i being what you are testing for primality. I'm going
to refer to this as your outer for loop.
Where you go wrong is to needlessly execute a while loop to test for primality.
Once you have established the i value you are testing, what you want to do is to
test whether there is any factor of i which is other than 1 or i. To do that, you
can use a simple, inner for loop which iterates a value j (so-called to avoid
confusion with your q) to determine whether i is divisible by j with zero remainder using
a mod test:
if it is, there is no point in continuing with the inner, j loop.
The next thing to consider is what should be the upper limit of the
loop for j := ... to ... should be. It is pointless to consider values
of j which are higher than the square root of i for the obvious reason
that if i has an intger factor greater than that, it must also have one
which is lower.
If the j loop completes without finding a factor, i is prime.
Try coding the inner, j loop, and you will see how the result is vastly
simpler (and more predictable) than your existing code, and with very few
opportunities for coding error, and vastly simpler to debug because execution
just "falls" through it for each value of i.
Btw, I completely agree with #TomBrunberg about structured coding as a general proposition, but I think that the two nested for loops you need here don't really need separating into different procedures/functions, though you might try
that once you've got the code working properly.
The causes of your error are a mix between the fact that the problem is highly depending on your input and that you are not treating some cases in else causes.
As an example, I ran your program with a=20 and b=30. The program ran into the for loop, which is correct. However, the (b>2) and (b<=10) condition is false, which made the compiler go to the else branch. However, the first thing it met there was while (q>=2) and (b<=10) which is, from the start, false. There it bounces back as you said in your question.
With a=2 and b=9, your program has a total different behavior.
How to fix it? I guess you first have to clarify what you want. Then, I think, the fix will be obvious.
Your program lacks structure because the whole program is crammed in the main procedure.
As a consequence of the previous, it has too many 'indentation levels' or 'logical chains' to be readable and manageable. With indentation levels or logical chains I mean e.g. your:
'for<condition> - if<condition> - while<condition> - if<condition> - if<condition> - if<condition> - writeln().
Because of the long chains of conditions, it is hard to evaluate what a change will effect, and you might find yourself deeper and deeper in trouble, when you try to fix something.
I suggest you ditch what you have now, and divide your program into procedures / functions according to main operations: for example GetUserEntry(var a, b: integer), function IsPrime(x: integer): boolean, procedure ShowResult() and the main program (GetUserEntry, for a to b if IsPrime then add to outstring, ShowResult(outstring)).
Finally, format your code to be readable using proper indentation.

Darts Program in Pascal

I would like to create a program for darts, I walked up to a problem.
s1 := Form1.Edit1.Text;
s2 := Form1.Edit2.Text;
s3 := Form1.Edit3.Text;
x1 := StrToFloat(s1);
x2 := StrToFloat(s2);
x3 := StrToFloat(s3);
score1 := (score1 - x1 - x2 - x3);
ss1 := FloatToStr(score1);
Form1.Edit7.Text := ss1;
score1 should be 501 at start and count down, so score 1 is at the start 501 you fill in 3 numbers and it should be 501-1-1-1 (for example) and then the next time it should be 498-1-1-1
How can i do this?
I dont have any problems or errors, i just dont know how to do this.
I use lazarus to write the program.
I hope i explained this well enough.
Ok, I will outline how you might do this, but leave the coding up to you.
First you need to read up about programming loops - see for example
https://www.tutorialspoint.com/pascal/pascal_loops.htm
Typically, with a task like this, you start by setting some initial condition(s) before the loop first executes. In your case, I think it would be better to back-track slightly from there and choose a better name for your score variable. Personally, I would base the name on Target, and actually have two variables, Target, that you initialize before the loop (to 501) and RunningTarget that you initialize to equal Target before the loop, and update each time around the loop (as in your score1 := (score1 - x1 - x2 - x3))
The type of loop - see the article - is up to you. It will need a terminating condition which decodes whether to continue looping or to stop. Again that's for you to decide and code.
Finally, you need to think about why you feel the need to call FloatToStr and what you are trying to achieve by this - after all the RunningTotal's value will be a whole number, won't it?
Have fun!
Btw, the reason I suggested thinking about a different variable name is that you should always have in the back of your mind whether it will mean the same thing to you in 6 months' time - or to another reader. To me, 'score' sounds like the value should be increasing, whereas your code will do the exact opposite.

fpc: how to initialize a global variable before it is initialized

I am making a simple text game in pascal (a real beginner one). There is a general routine, that is repeated several times (the cycles variable, representing the levels). In the beginning of the routine there is a part where character`s name is asked. If the general repeat loop is complete or aborted at some level(1-4), the game goes back to the first sort of menu. I want the name to be asked only the first time, but, of course, I get the "variable "cycles" does not seem to be initialized" warning. Is there a way to restructure the code to avoid it?
Thanks.
The code excerpt (unnecessary details left behind):
program rpg_text_game;
var
game_action:char;
name:string;
cycles:1..5;
begin
repeat
writeln('Welcome to the game.');
writeln('To continue press "g",');
writeln('to read the license of this game press "i",');
writeln('and to quit press "q" and "enter": ');
readln(game_action);
case game_action of
'i', 'I':
{shows license}
'g', 'G':
{game begins}
if not (cycles in [2,3,4,5]) then
begin
writeln('Please enter your name: ');
readln(name);
end;
repeat
cycles:=1; //is initialized here
{actual game process - score is calculated based on *cycles* amount, that adds +1 with each tick ("if success then cycles:=cycles+1")}
{cycles - 1,2,3,4,5}
writeln('Do you want to try again, y/n?');
readln(game_action);
until(game_action='n') or (game_action='N');
until (game_action='q') or (game_action='Q');
writeln();
writeln('Press enter to quit');
readln();
end.
So, how to initialize/change the cycles variable (or even any other) to avoid that message and not to cheat by turning off the compiler hint option?
If cycles is a global variable, like in your example code, then simply do, in the main block of the program, before you start anything:
begin
cycles := 1;
game_action := Chr(0);
{ etc... }
...
end.
That is how you generally initialize global variables: in the main begin/end. block. Some versions of Pascal also allow (for global variables):
var
cycles: 1..5 = 1;
{ etc... }
but others don't. I don't know if your Pascal allows it. If it does, you won't have to initialize in the main block anymore. But note that that probably doesn't work for local variables of a function or procedure. There, you will probably have to use the (outer) begin/end; block of the function or procedure.
FWIW, the main block of a program can usually be found at the very end of the program, after all the const, type, var, procedure and function declarations and it ends with a dot (.).
Also note that the comment is right: split your program into separate functions and procedures, each with their own single task, and pass any information necessary to them. Do not write monolithic blocks of code. That is hard to read and hard to maintain. For instance, for each (or most) of your case items, create a separate procedure with the necessary parameters and call those from your case statement. That makes your code much easier to read, also for you.
In the first iteration of the loop in the code as is, cycles is read (by the IF NOT (cycles in [])) before being initialized. The compiler rightfully emits a warning for that.
The solution is simple, initialize it before the first REPEAT, or if you go more object pascal style, like Rudy says.

Fortran Bus Error on allocating a large matrix (gfortran)

When I compile the following Fortran code with gfortran and run it, it gives me 'signal SIGBUS: Access to undefined portion of a memory object', whenever n>=180. I'm running this on a Mac OSX Mavericks.
PROGRAM almatrix
IMPLICIT NONE
INTEGER :: i,j,n
REAL,ALLOCATABLE :: a(:,:)
READ(*,*)n
ALLOCATE(a(n+1,n+1))
DO i=0,n
DO j=0,n
a(i,j)=0.0
END DO
END DO
DEALLOCATE(a)
END PROGRAM almatrix
I understood that instead of
ALLOCATE(a(n+1,n+1))
this
ALLOCATE(a(n+1,n+1),STAT=err)
IF(err /= 0) STOP
would prevent crashing. It didn't, however. Why?
I tried to look at similar problems, but so far they haven't helped.
I tried to compile with -Wall, -g, -fcheck=all, as suggested in another answer, but those didn't give me warnings.
I've also noticed before, that unlike with C, Fortran usually does not give bus errors when using small dynamic arrays and not deallocating them.
The problem isn't directly with the allocate statement, but with accessing the resulting array. [Note also that that an array 181x181 is not "large".] As there is nothing wrong with the allocation, err will indeed be zero.
From that allocate one is left with an array a which has elements a(1,1), a(2,1), ..., a(n+1,1), ..., a(n+1,n+1). So, a(0,0) (the first access in the loop) is not valid.
There are two options: request that the array elements be a(0,0) to a(n,n) as the loop wants, or change the loop:
allocate(a(0:n,0:n))
or
do i=1,n+1
do j=1,n+1
a(j,i) = 0 ! Note I've changed the order to Fortran-friendly
end od
end do
Finally, those loops aren't even necessary:
allocate(a(0:n,0:n))
a = 0.
or even
allocate(a(0:n,0:n), source=0.)
if you have a compiler later than Fortran 95.

Resources