Possible reasons for computer freeze from an app

I have written a Delphi app for decryption (specifically for the Vigenere cypher).
My program uses “Hill Climbing” for progressively solving the encryption key word.
The program works fine and will solve the encryption word.

However after running the code and getting the key, the entire computer essentially freezes for a minute or so.
The mouse still works during this “freeze” (so not totally frozen) but there is no response form mouse clicking anything in the app, or anything on the desktop.

After a minute or two, the computer comes responsive, and finally processes all the mouse clicks that had occurred during the “freeze”.

Anyway, I am assuming the reason is the computer is freezing due to cleaning up memory allocations made during the “Hill Climbing” search.

I tried to correct it by specifically coding everything to properly create, close, and free resources.
Yet this “freeze” still occurs.

I am just wondering if anyone else has had this happen, and if they know what could be the cause!

how much memory is it actually allocating? does it get into swap file territory?

Only pre-declared string sizes. No Swap files.

This “freeze” also happens on my “Crypto Substitution” solver.
That code is small enough to include in full below.
(The Vigenere cypher code has many more lines due to animating the Vigenere table.)

If anyone is interested the code for tje “Crypto Substitution” is below.
There is no real Memory allocation, swap space etc.
But after running this code for a few minutes, and stoping the solver, the computer does the “freeze” for a minute or so.


const
   Sinkov: array [1..26] of real =
    (  4.404820427, 2.381601633, 3.528971492, 3.853451829, 4.972741108, 3.448928784, 2.901421594,
       3.628185385, 4.402917994, 0.600056757, 1.190549784, 3.700478590, 3.313781883, 4.481117537,
       4.225697658, 3.390024081, 1.358123484, 4.432930965, 4.218853897, 4.626061545, 3.363457054,
       2.834519680, 2.852631430, 1.635755221, 3.067536006, 0.085157808
    );


function TMainwin.GetFitness(var decstr:string):integer;
var lv:integer;
    rval:real;
begin
   // use sinkov stats for fitness
   rval:= 0;
   for lv:= 1 to length(decstr) do
   begin
      cyc:= ord(decstr[lv])-64;
      if (cyc>=0)and(cyc<26) then rval:= rval+Sinkov[cyc];
   end;
   result:= round(rval*10);
end;

function RandKey:string;
var key:string;
    tchr:char;
    num,lop,cyc:integer;
begin    
   key:= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
   // randomly swap 100 key chars to get random substitution key
   for num:= 1 to 100 do
   begin
      lop:= random(26)+1;
      cyc:= random(26)+1; while (cyc=lop) do cyc:= random(26)+1;
      tchr:= key[lop]; key[lop]:= key[cyc]; key[cyc]:= tchr;
   end;
   result:= key;
end;

procedure TMainwin.ButGoclick(sender: Tobject);
var tmps,encstr,bestkey,keystr,newkey,decstr:string;
    lop,cyc,num1,num2,bestscore,trialscore,score:integer;
    tchr:char;
begin
   lboxresult.items.clear;
   encstr:= UpperCase(EncTextBox.text);

   lboxresult.items.add('Encrypted string: '+encstr);
   lboxresult.items.add(' ');

   stopit:= false;  // global variable

   bestkey:= '';
   bestscore:= -100;
   repeat
      keystr:= RandKey;
      trialscore:= -100;
      lop:= 1;
      while (lop<1000)and(not(stopit)) do
      begin
         // alter key by swapping 2 random letters
         newkey:= keystr;
         num1:= random(26)+1;
         num2:= random(26)+1; while (num2=num1) do num2:= random(26)+1;
         tchr:= newkey[num1]; newkey[num1]:= newkey[num2]; newkey[num2]:= tchr;
         // decrypt
         decstr:= '';
         for cyc:= 1 to length(encstr) do
         begin
            num1:= ord(encstr[cyc])-ord('A')+1;
            decstr:= decstr+newkey[num1];
         end;
         // fitness
         score:= GetFitness(decstr);
         if (score>trialscore)  then
         begin
            trialscore:= score;
            keystr:= newkey;
            {if (score>=bestscore) then} lboxresult.items.add(format('%6d %s - %s',[trialscore,decstr,keystr]));
            lboxresult.topindex:= lboxresult.items.count-1;
            lop:= 1;
            Application.Processmessages;
         end;
         inc(lop);
      end;
      if (trialscore>bestscore) then
      begin
         bestscore:= trialscore;
         bestkey:= keystr;
         Editbest.text:= format('%6d %s - %s',[bestscore,decstr,bestkey]);
      end;
      Application.Processmessages;
   until (stopit);

end;

For one thing …

      cyc:= ord(decstr[lv])-64;
      if (cyc>=0) and (cyc<26) then rval:= rval+Sinkov[cyc];

      'A' -> cyc = 1
      'Z' -> cyc = 26
const
       Sinkov: array [1..26] of real = ...
// But ... 
       if cyc in [ 0..25 ] then ...

Is there a problem here?

Also … do you have an example encrypted string ?

Found some examples on Wikipedia: https://en.wikipedia.org/wiki/Substitution_cipher
SIAA ZQ LKBA. VA ZOA RFPBLUAOAR!
MCDD GS JIAD. WD GPD NHQAJVDPDN!

However, that crashes at the first space! The encryption string needs to be stripped only accepting letters.

SIAAZQLKBAVAZOARFPBLUAOAR
MCDDGSJIADWDGPDNHQAJVDPDN

The cyc index it is indeed an issue because the value is 1..26 (-64 = -ord('A')+1), but the “equal” is in the wrong position (should move from 0 to 26)…
cyc:= ord(decstr[lv])-64; if (cyc>0) and (cyc<=26) then rval:= rval+Sinkov[cyc];

There are a lot of uncecessary random(26)+1 in this code which could have been avoided by declaring Sinkov: array [0..25]

Nevertheless, I could not reproduce any “freeze”. The issue might be on the “other side” aka animating the Vigenere table.

Yep that ( (cyc>=0)and(cyc<26) ) line correction was indeed an error

Although it did not stop the code from (eventual) solving for the key.
I also note I did not define the “cyc” in the local “var” declaration of that function (it was defined in a global variable).
Anyway, fixing the above still does not stop the “freezing” after running the code.

Found some examples on Wikipedia
SIAA ZQ LKBA. VA ZOA RFPBLUAOAR!
MCDD GS JIAD. WD GPD NHQAJVDPDN!
However, that crashes at the first space!

Yea good encryption NEVER includes spaces (for the spacing out letter to words gives a cipher weakness).

other side aka animating the Vigenere table.

As mentioned, this is NOT the Vigenere decryption computer code.
This is the “Substitution cipher” code. That code section given, is the entire code.
The code searches for the letter Substitution key, and outputs the results to a ListBox and Editbox. There is NO other code animation, or otherwise, running during this solve.

I also tried running the code on my laptop (I previously only ran the code on my higher spec desktop computer).
This “freeze” was also NOT present on the laptop!
So and even greater mystery, it is definably now something to do with my desktop computer.

Likely memory or harddisk failure.

Better download and run memtest as well as a SMART check or HDD Sentinel check.

Yes, I turned it into a console app.
It had no problems running, even 'tho it wasn’t making sensible output for me.

But you have ProcessMessages in there .. that might indicate there can be a better approach to the UI aspects.

One possible issue that I unfortunately ignored (aka “fixed”) was the massive number of lines in the list:

 {if (score>=bestscore) then} lboxresult.items.add(format('%6d %s - %s',[trialscore,decstr,keystr]));

Even after uncommenting the if.

Maybe that freeze is simply the amount of time used for cleaning up a massive list.

Try to limit that output. Add to list only if score > bestscore.
If the system looks unresponsive for not finding a better score to visually progress things, add the current evaluating key in an edit. That would change without allocating more and more memory. Maybe also add a counter of how many keys were verified.