Recent

Author Topic: Project1 raised exception class: External : SIGSEGV at addres 403920  (Read 6707 times)

PascalDragon

  • Hero Member
  • *****
  • Posts: 6381
  • Compiler Developer
Yes, that would indeed work as well ;)

Raf20076

  • Full Member
  • ***
  • Posts: 184
    • https://github.com/Raf20076
Hi Guys again

Whe I got again error exception class: External : SIGSEGV at addres 408B44 cmpl $0x0, -0x8(%eax) which points at SYSTEM$$_NEWANSISTRING$$LONGINT$$POINTER(79)

I used Call Stack ( View->Debug Windows->Call Stack)and what I have got.

(I have already used three different hunspell.dll and versions and still got this error)

I have found also this https://sourceforge.net/p/hunspell/bugs/251/

Code: Pascal  [Select][+][-]
  1. #0 fpc_ansistr_incr_ref at :0
  2. #1 THUNSPELL__SPELL(0xb35ed813 <error: Cannot access memory at address 0xb35ed813>, <error reading variable>) at hunspell.pas:150
  3. #2 TFORM1__BUTTON1CLICK(0x1e0820, <error reading variable>) at unit1.pas:153
  4. #3 TCONTROL__CLICK(<error reading variable>) at .\include\control.inc:2913
  5. #4 TBUTTONCONTROL__CLICK(<error reading variable>) at .\include\buttoncontrol.inc:55
  6. #5 TCUSTOMBUTTON__CLICK(<error reading variable>) at .\include\buttons.inc:169
  7. #6 TBUTTONCONTROL__WMDEFAULTCLICKED({MSG = 66567, WPARAM = 0, LPARAM = 0, RESULT = 0, WPARAMLO = 0, WPARAMHI = 0, WPARAMFILLER = {}, LPARAMLO = 0, LPARAMHI = 0, LPARAMFILLER = {}, RESULTLO = 0, RESULTHI = 0, RESULTFILLER = {}}, <error reading variable>) at .\include\buttoncontrol.inc:21
  8. #7 SYSTEM$_$TOBJECT_$__$$_DISPATCH$formal at :0
  9. #8 VMT_$STDCTRLS_$$_TBUTTONCONTROL at :0
  10. #9 ?? at :0
  11. #10 TWINCONTROL__WNDPROC({MSG = 66567, WPARAM = 0, LPARAM = 0, RESULT = 0, WPARAMLO = 0, WPARAMHI = 0, WPARAMFILLER = {}, LPARAMLO = 0, LPARAMHI = 0, LPARAMFILLER = {}, RESULTLO = 0, RESULTHI = 0, RESULTFILLER = {}}, <error reading variable>) at .\include\wincontrol.inc:5419
  12. #11 DELIVERMESSAGE(0x1e0820, <error reading variable: Attempt to dereference a generic pointer.>) at lclmessageglue.pas:112
  13. #12 TWINDOWPROCHELPER__DOWINDOWPROC(<error reading variable>) at win32callback.inc:2515
  14. #13 WINDOWPROC(397478, 273, 2080, 135330) at win32callback.inc:2677
  15. #14 CUSTOMFORMWNDPROC(397478, 273, 2080, 135330) at win32wsforms.pp:387
  16. #15 gapfnScSendMessage at :0
  17. #16 ?? at :0
  18. #17 gapfnScSendMessage at :0
  19. #18 ADJUSTFORMBOUNDS(0x0, <error reading variable: Cannot access memory at address 0x7bf8103e>) at win32wsforms.pp:306
  20. #19 USER32!DefWindowProcW at :0
  21. #20 ?? at :0
  22.  





Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12288
  • Debugger - SynEdit - and more
    • wiki
Working of the wiki (which means I have no line numbers to the code), and not having any info what happens in your unit1....

It would be good, if you could attach the exact hunspell code you use. And (a cut down) version of unit1, with just enough code to reproduce the issue.


I would guess the error happens in
Code: Pascal  [Select][+][-]
  1. function THunspell.Spell(Word: string): boolean;
  2. begin
  3.     Result := hunspell_spell(Speller, PChar(Word))
  4. end;
  5.  
"Word" is the only string. And it is corrupted.

So the question is what happened in uint1 to the variable that you passed as "word" to this function? And where did it get its value from?

--
If you are on linux, you may also try running your app under valgrind. There is a good chance that this gives more feedback.

Raf20076

  • Full Member
  • ***
  • Posts: 184
    • https://github.com/Raf20076
I will upload  it soon

Raf20076

  • Full Member
  • ***
  • Posts: 184
    • https://github.com/Raf20076
It seems to me you maybe right it's about Word maybe change Word for aWord as someone said because Word is reserved?

Hunspell Interface

Code: Pascal  [Select][+][-]
  1. {$MODE objfpc}{$H+}
  2. unit hunspell;
  3.  
  4. {   Hunspell interface.
  5.     Based on code that seems to appear in lots of places in the Lazarus Forum
  6.     and elsewhere.
  7.  
  8.     With additions and corrections by dbannon to make it a little easier to use.
  9.  
  10.     As such, its assumed to be free to use by anyone for any purpose.
  11. }
  12.  
  13. {   A Unit to connect to the hunspell library and check some spelling.
  14.     First, create the class, it will try and find a library to load.
  15.     Check ErrorMessage.
  16.     Then call SetDictionary(), with a full filename of the dictionary to use.
  17.     If GoodToGo is true, you can call Spell() and Suggests()
  18.     otherwise, look in ErrorString for what went wrong.
  19.  
  20.     Look in FindLibrary() for default locations of Library.
  21. }
  22.  
  23.  
  24. interface
  25. uses Classes, dynlibs;
  26.  
  27. type
  28.   THunspell_create = function(aff_file: PChar; dict_file: PChar): Pointer; cdecl;
  29.   THunspell_destroy = procedure(spell: Pointer); cdecl;
  30.   THunspell_spell = function(spell: Pointer; word: PChar): Boolean; cdecl;
  31.   THunspell_suggest = function(spell: Pointer; out slst: PPChar; word: PChar): Integer; cdecl;
  32.   THunspell_analyze = function(spell: Pointer; var slst: PPChar; word: PChar): Integer; cdecl;
  33.   THunspell_stem = function(spell: Pointer; var slst: PPChar; word: PChar): Integer; cdecl;
  34.   THunspell_free_list = procedure(spell: Pointer; var slst: PPChar; n: integer); cdecl;
  35.   THunspell_get_dic_encoding = function(spell: Pointer): PChar; cdecl;
  36.   THunspell_add = function(spell: Pointer; word: PChar): Integer; cdecl;
  37.   THunspell_remove = function(spell: Pointer; word: PChar): Integer; cdecl;
  38.  
  39.    { THunspell }
  40.  
  41.   THunspell = class
  42.   private
  43.     Speller: Pointer;
  44.         { Loads indicated library, returns False and sets ErrorMessage if something wrong }
  45.     function LoadHunspellLibrary(LibraryName: AnsiString): Boolean;
  46.   public
  47.             { set to True if speller is ready to accept requests }
  48.     GoodToGo : boolean;
  49.             { empty if OK, contains an error message if something goes wrong }
  50.     ErrorMessage : ANSIString;
  51.             { Will have a full name to library if correctly loaded at create }
  52.     LibraryFullName : string;
  53.             { Will have a "first guess" as to where dictionaries are, poke another name in
  54.             and call FindDictionary() if default did not work }
  55.     constructor Create();
  56.     destructor Destroy; override;
  57.             { Returns True if word spelt correctly }
  58.     function Spell(Word: string): boolean;
  59.             { Returns with List full of suggestions how to spell Word }
  60.     procedure Suggest(Word: string; List: TStrings);
  61.             { untested }
  62.     procedure Add(Word: string);
  63.             { untested }
  64.     procedure Remove(Word: string);
  65.             { returns a full library name or '' if it cannot find anything suitable }
  66.     function FindLibrary(out FullName : AnsiString) : boolean;
  67.             { returns true if it successfully set the indicated dictionary }
  68.     function SetDictionary(const FullDictName: string) : boolean;
  69.     function SetNewLibrary(const LibName : string) : boolean;
  70.   end;
  71.  
  72. var Hunspell_create: THunspell_create;
  73. var Hunspell_destroy: THunspell_destroy;
  74. var Hunspell_spell: Thunspell_spell;
  75. var Hunspell_suggest: Thunspell_suggest;
  76. var Hunspell_analyze: Thunspell_analyze;
  77. var Hunspell_stem: Thunspell_stem;
  78. var Hunspell_get_dic_encoding: Thunspell_get_dic_encoding;
  79. var Hunspell_add: THunspell_add;
  80. var Hunspell_free_list: THunspell_free_list;
  81. var Hunspell_remove: THunspell_remove;
  82.  
  83. var HunLibLoaded: Boolean = False;
  84. var HunLibHandle: THandle;
  85.  
  86. implementation
  87.  
  88. uses LazUTF8, SysUtils, {$ifdef linux}Process, {$else} Forms, {$endif} LazFileUtils;
  89. // Forms needed so we can call Application.~
  90.  
  91. { THunspell }
  92.  
  93. function THunspell.LoadHunspellLibrary(libraryName: Ansistring): Boolean;
  94. begin
  95.     Result := false;
  96.     HunLibHandle := LoadLibrary(PAnsiChar(libraryName));
  97.     if HunLibHandle = NilHandle then
  98.         ErrorMessage := 'Failed to load library ' + libraryName
  99.     else begin
  100.         Result := True;
  101.         Hunspell_create := THunspell_create(GetProcAddress(HunLibHandle, 'Hunspell_create'));
  102.         if not Assigned(Hunspell_create) then Result := False;
  103.         Hunspell_destroy := Thunspell_destroy(GetProcAddress(HunLibHandle, 'Hunspell_destroy'));
  104.         if not Assigned(Hunspell_destroy) then Result := False;
  105.         Hunspell_spell := THunspell_spell(GetProcAddress(HunLibHandle, 'Hunspell_spell'));
  106.         if not Assigned(Hunspell_spell) then Result := False;
  107.         Hunspell_suggest := THunspell_suggest(GetProcAddress(HunLibHandle, 'Hunspell_suggest'));
  108.         if not Assigned(Hunspell_suggest) then Result := False;
  109.         Hunspell_analyze := THunspell_analyze(GetProcAddress(HunLibHandle, 'Hunspell_analyze'));  // not used here
  110.         if not Assigned(Hunspell_analyze) then Result := False;
  111.         Hunspell_stem := THunspell_stem(GetProcAddress(HunLibHandle, 'Hunspell_stem'));           // not used here
  112.         if not Assigned(Hunspell_stem) then Result := False;
  113.         Hunspell_get_dic_encoding := THunspell_get_dic_encoding(GetProcAddress(HunLibHandle, 'Hunspell_get_dic_encoding'));   // not used here
  114.         if not Assigned(Hunspell_get_dic_encoding) then Result := False;
  115.         Hunspell_free_list := THunspell_free_list(GetProcAddress(HunLibHandle, 'Hunspell_free_list'));
  116.         if not Assigned(Hunspell_free_list) then Result := False;
  117.         Hunspell_add := THunspell_add(GetProcAddress(HunLibHandle, 'Hunspell_add'));
  118.         if not Assigned(Hunspell_add) then Result := False;
  119.         Hunspell_remove := THunspell_remove(GetProcAddress(HunLibHandle, 'Hunspell_remove'));
  120.         if not Assigned(Hunspell_remove) then Result := False;
  121.         HunLibLoaded := Result;
  122.     end;
  123.     if ErrorMessage = '' then
  124.         if not Result then ErrorMessage := 'Failed to find functions in ' + LibraryName;
  125. end;
  126.  
  127. constructor THunspell.Create();
  128. begin
  129.     ErrorMessage := '';
  130.     if Not FindLibrary(LibraryFullName) then begin
  131.         ErrorMessage := 'Cannot find Hunspell library';
  132.         exit();
  133.     end;
  134.     LoadHunspellLibrary(LibraryFullName);    // will flag any errors it finds
  135.     Speller := nil;           // we are not GoodToGo yet, need a dictionary ....
  136. end;
  137.  
  138. destructor THunspell.Destroy;
  139. begin
  140.     if (HunLibHandle <> 0) and HunLibLoaded then begin
  141.         if Speller<>nil then hunspell_destroy(Speller);
  142.         Speller:=nil;
  143.         if HunLibHandle <> 0 then FreeLibrary(HunLibHandle);
  144.         HunLibLoaded := false;
  145.     end;
  146.     inherited Destroy;
  147. end;
  148.  
  149. function THunspell.Spell(Word: string): boolean;
  150. begin
  151.     Result := hunspell_spell(Speller, PChar(Word))
  152. end;
  153.  
  154. procedure THunspell.Suggest(Word: string; List: TStrings);
  155. var i, len: Integer;
  156.         SugList, Words: PPChar;
  157. begin
  158.     List.clear;
  159.     If Word = '' Then exit else Word := Word+#0;
  160.     try
  161.       len := hunspell_suggest(Speller, SugList, PChar(Word));
  162.       Words := SugList;
  163.       For i := 0 to len -1 do
  164.       List.Add(Words[i]^);
  165.     finally
  166.         Hunspell_free_list(Speller, SugList, len);
  167.     end;
  168. end;
  169.  
  170. procedure THunspell.Add(Word: string);
  171. begin
  172.     Hunspell_add(Speller, Pchar(Word));
  173. end;
  174.  
  175. procedure THunspell.Remove(Word: string);
  176. begin
  177.     Hunspell_remove(Speller, Pchar(Word));
  178. end;
  179.  
  180. function THunspell.FindLibrary(out FullName : ANSIString):boolean;
  181. var
  182.     {$ifdef LINUX} I : integer = 1; {$endif}
  183.     Info : TSearchRec;
  184.     Mask : ANSIString;
  185. begin
  186.     Result := False;
  187.     {$IFDEF LINUX}
  188.     // Assumes ldconfig always returns same format, better than searching several dirs
  189.     if RunCommand('/bin/bash',['-c','ldconfig -p | grep hunspell'], FullName) then begin
  190.         while UTF8Pos(' ', FullName, I) <> 0 do inc(I);
  191.         if I=1 then exit();
  192.         UTF8Delete(FullName, 1, I-1);
  193.         UTF8Delete(FullName, UTF8Pos(#10, FullName, 1), 1);
  194.         Result := True;
  195.     end;
  196.     exit();
  197.     {$ENDIF}
  198.     {$IFDEF WINDOWS}            // Look for a dll in application home dir.
  199.     Mask := '*hunspell*.dll';
  200.     FullName := ExtractFilePath(Application.ExeName);
  201.     {$endif}
  202.     {$ifdef DARWIN}
  203.     Mask := 'libhunspell*';
  204.     FullName := '/usr/lib/';
  205.     {$endif}
  206.     if FindFirst(FullName + Mask, faAnyFile and faDirectory, Info)=0 then begin
  207.         FullName := FullName + Info.name;
  208.         Result := True;
  209.     end;
  210.     FindClose(Info);
  211. end;
  212.  
  213. function THunspell.SetDictionary(const FullDictName: string) : boolean;
  214. var
  215.     FullAff : string;
  216. begin
  217.     FullAff := FullDictName;
  218.     UTF8Delete(FullAff, UTF8Length(FullAff) - 2, 3);
  219.     FullAff := FullAff + 'aff';
  220.     if Speller <> Nil then
  221.         hunspell_destroy(Speller);
  222.     Speller := hunspell_create(PChar(FullAff), PChar(FullDictName));
  223.     GoodToGo := Speller <> Nil;
  224.     if not GoodToGo then
  225.         ErrorMessage := 'Failed to set Dictionary ' + FullDictName;
  226.     Result := GoodToGo;
  227. end;
  228.  
  229. function THunspell.SetNewLibrary(const LibName: string): boolean;
  230. begin
  231.     LibraryFullName := LibName;
  232.     Result := LoadHunspellLibrary(LibraryFullName);
  233. end;
  234.  
  235. end.
  236.  
  237.  

My code
Code: Pascal  [Select][+][-]
  1. //SpellChecker by Raf20076, Poland 2019
  2. //Create new program
  3. //Place hunspell.pass unit in your application folder (or create one and fill it
  4. //with
  5. //Place libhunspell.dll in your application folder
  6. //Place dictionary in your application folder, (two files) like pl_PL.aff, pl_PL.dic
  7. //Ditionary must be encoded in UTF8
  8.  
  9. //On Form1 place component TButton (Button1) from Standard Tab
  10. //On Form1 place component TMemo (Memo1) from Standard Tab
  11. //On Form1 place component TListbox (ListBox1) from Standard Tab (here misspelt
  12. //words will be shown
  13.  
  14. //Erorrs, generally it works very good but
  15. //If there is a big space between last sentence and the new one in Memo1
  16. //sometimes it couses an error; Access Violation; needs more testing
  17.  
  18. unit Unit1;
  19.  
  20. {$mode objfpc}{$H+}
  21.  
  22.  
  23. interface
  24.  
  25. uses
  26.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
  27.   LazFileUtils, LCLProc, LazUtils, LazUtf8;
  28.  
  29. type
  30.  
  31.   { TForm1 }
  32.  
  33.   TForm1 = class(TForm)
  34.     Button1: TButton;
  35.     Label1: TLabel;
  36.     Label2: TLabel;
  37.     ListBox1: TListBox;
  38.     ListBox2: TListBox;
  39.     Memo1: TMemo;
  40.     procedure Button1Click(Sender: TObject);
  41.     procedure FormCreate(Sender: TObject);
  42.     procedure FormDestroy(Sender: TObject);
  43.   private
  44.  
  45.   public
  46.  
  47.   end;
  48.  
  49. var
  50.   Form1: TForm1;
  51.  
  52.  
  53. implementation
  54.  
  55. uses hunspell;
  56.  
  57. var
  58. SpellCheck: THunspell;
  59.  
  60.  
  61. {$R *.lfm}
  62.  
  63. { TForm1 }
  64.  
  65. procedure TForm1.FormCreate(Sender: TObject);
  66. begin
  67.  
  68.    SpellCheck := THunspell.Create();
  69.    SpellCheck.SetDictionary('pl_PL.dic');//Load dictionary
  70.    SpellCheck.GoodToGo := True;
  71.  
  72.  
  73. end;
  74.  
  75. {Extract words from string: non characters, spaces, carriagereturn aware}
  76.  
  77. function ArrayValueCount(const InputArray: Array of string): Integer;
  78. {Count elements in array}
  79. var
  80.     i:Integer;
  81.     begin
  82.         result := 0;
  83.         for i := low(InputArray) to high(InputArray) do
  84.         if InputArray[i] <> ' ' then  // 'between them one space'
  85.             inc(result);
  86.     end;
  87.  
  88. function StripOffNonCharacter(const aString: string): string;
  89. {Remove non characters from string}
  90.  
  91. var
  92.   a: Char;
  93. begin
  94.   Result := '';
  95.   for a in aString do begin //below punctuation marks, numbers to remove from string
  96.       if not CharInSet(a, ['.', ',', ';', ':', '!', '/',
  97.       '?', '@', '#', '$', '%', '&', '*', '(', ')', '{',
  98.       '}', '[', ']', '-', '\', '|', '<', '>', '''', '"', '^',
  99.       '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '_', '+',
  100.       '=', '~'])  then //'„', '”'])these marks make error: Ordinal expression expected, need to be fixed
  101.       begin
  102.         Result := Result + a;
  103.       end;
  104.     end;
  105.  
  106. end;
  107.  
  108.  
  109. function ReplaceCarriageReturn(s: string) : string;
  110. {Replace carriagereturn with one space}
  111. var
  112.   i: Integer;
  113.  
  114. begin
  115.   Result:=s;
  116.   for i := 1 to Length(Result) do
  117.   if Result[i] in [#3..#13] then
  118.   Result[i] := ' ';//'Between them one space'
  119.   end;
  120.  
  121.  
  122. procedure TForm1.Button1Click(Sender: TObject);
  123.  
  124.   {Check spelling}
  125.  
  126.  var
  127.      i : Integer;
  128.      MAX : Integer;
  129.      FillInArrayWithWords:TStringArray;
  130.      FillInString1: String;
  131.      FillInString2: String;
  132.  
  133.  
  134. begin
  135.  
  136.     ListBox1.clear;
  137.     ListBox1.Items.Clear;
  138.  
  139.     FillInString1 := ReplaceCarriageReturn(Memo1.Lines.Text);//take text from Memo1; replace carriage return
  140.     //with one space (using ReplaceCarriageReturn function) and put into FillInString1
  141.  
  142.     FillInString2 := StripOffNonCharacter(FillInString1);//remove all non characters from FillInString1
  143.     //(using StripOffNonCharacter function)  and put string without non charachters into FillInString2
  144.  
  145.     FillInArrayWithWords := FillInString2.split(' '); //Split string into words with ' ' one space
  146.     //(using .split) and put separate words into array FillInArrayWithWords
  147.  
  148.     MAX := ArrayValueCount(FillInArrayWithWords); //Give how many elements are in array
  149.     //(using function ArrayValueCount)
  150.  
  151.     for i := 0 to MAX do
  152.  
  153.     if not SpellCheck.Spell(FillInArrayWithWords[i]) then ListBox1.Items.add(FillInArrayWithWords[i])
  154.     //Take word from array and check in dictionary through hunspell (using SpellCheck.Spell function)
  155.     //If word is not in dictionary show it in Listbox as an error
  156.  
  157. end;
  158.  
  159. procedure TForm1.FormDestroy(Sender: TObject);
  160. begin
  161.     SpellCheck.free;
  162.     SpellCheck := nil;
  163. end;
  164.  
  165. end.
  166.  
  167.  

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12288
  • Debugger - SynEdit - and more
    • wiki
It seems to me you maybe right it's about Word maybe change Word for aWord as someone said because Word is reserved?

"word" is a type. In this particular case I think if there was a conflict, you would get (in that case) a compile error.
But still it will help readability to change it....

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12288
  • Debugger - SynEdit - and more
    • wiki
TForm1.Button1Click
Code: Pascal  [Select][+][-]
  1.         for i := 0 to MAX do

Maybe "0 to Max-1" ?

Are you compiling with range checks enabled? You should.

Also, if ArrayValueCount sees a ' ' in the middle of the array, it may not count it. But your loop will use that value and instead discard a value at the end.


Raf20076

  • Full Member
  • ***
  • Posts: 184
    • https://github.com/Raf20076
Ok it was the problem

But in Hunspell Interface procedure sugestion must looks like this, otherwise doesn't work

Code: Pascal  [Select][+][-]
  1. procedure THunspell.Suggest(Word: string; List: TStrings);
  2. var i, len: Integer;
  3.         SugList, Words: PPChar;
  4. begin
  5.     List.clear;
  6.     try
  7.         len := hunspell_suggest(Speller, SugList, PChar(Word));
  8.         Words := SugList;
  9.         for i := 1 to len do begin
  10.             List.Add(Words^);
  11.  
  12.         end;
  13.     finally
  14.         Hunspell_free_list(Speller, SugList, len);
  15.     end;
  16. end;    
  17.  

I updated wiki website

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12288
  • Debugger - SynEdit - and more
    • wiki
Code: Pascal  [Select][+][-]
  1. for i := 1 to len do begin
Your loop started at 0. This loop starts at 1

0 to MAX => Max+1 elements
1 to len  => len elements

This loop does not use the index, so it could be changed to: for i := 0 to len-1 do

But your loop accesses an dynamic array. Arrays are 0-based. So you must start at 0.

But the way you calculated MAX, MAX could be length(array). And that would access an element outside the array.


jamie

  • Hero Member
  • *****
  • Posts: 7651
Code: Pascal  [Select][+][-]
  1. procedure THunspell.Suggest(Word: string; List: TStrings);
  2. var i, len: Integer;
  3.         SugList, Words: PPChar;
  4. begin
  5.     List.clear;
  6.     try
  7.         len := hunspell_suggest(Speller, SugList, PChar(Word));
  8.         Words := SugList;
  9.         for i := 1 to len do begin
  10.            // List.Add(Words^);
  11.            List.Add(Words[i]^); //Try this..
  12.  
  13.         end;
  14.     finally
  15.         Hunspell_free_list(Speller, SugList, len);
  16.     end;
  17. end;    
  18.  

 You didn't really fix anything, all you did was repeat the first return in the listing times the value of LEN

 Also I notice you did not rename the use of WORD to AWord..

 I give up.
The only true wisdom is knowing you know nothing

PascalDragon

  • Hero Member
  • *****
  • Posts: 6381
  • Compiler Developer
Ok it was the problem

But in Hunspell Interface procedure sugestion must looks like this, otherwise doesn't work

Code: Pascal  [Select][+][-]
  1. procedure THunspell.Suggest(Word: string; List: TStrings);
  2. var i, len: Integer;
  3.         SugList, Words: PPChar;
  4. begin
  5.     List.clear;
  6.     try
  7.         len := hunspell_suggest(Speller, SugList, PChar(Word));
  8.         Words := SugList;
  9.         for i := 1 to len do begin
  10.             List.Add(Words^);
  11.  
  12.         end;
  13.     finally
  14.         Hunspell_free_list(Speller, SugList, len);
  15.     end;
  16. end;    
  17.  

I updated wiki website
The code is wrong. This way the first string will be added len times to the list.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12288
  • Debugger - SynEdit - and more
    • wiki
The original code (or as it was posted earlier in this thread) is:
Code: Pascal  [Select][+][-]
  1.         for i := 1 to len do begin
  2.             List.Add(Words^);
  3.             Inc(PtrInt(Words), sizeOf(Pointer));
  4.          end;
And that will work. (At least if overflow checks are off, otherwise it needs PtrUInt).
PtrInt is always pointer sized, so the cast is portable.

It is hell to read, and for that might be rewritten. But that is not causing a crash.



 

TinyPortal © 2005-2018