How to debug fcl-db? lazarus / 16-Databases ---------------------------------------------------------------------- Mike.Cornflake · 2018-11-25 10:13 Looking for clues on how to debug inside bufdataset_parser.pp I'm building FPC in debug mode using Quotemake clean all LINKSMART=1  CREATESMART=1  DEBUG=1 OPTIMIZE=0  OPT="-gl -gw -godwarfsets -O-1" I'm using Lazarus Trunk, and fpc 3.0.4.  Neither my project, nor fpc is built with optimisations. I can step into bufdataset.pas with no problems.  Any breakpoint I set inside bufdataset_parser.pp actually end uo with code execution being stopped in the appropriate line inside BufDataset.pas.  For instance: If I breakpoint the first line inside TBufDatasetParser.Create; the debugger actually stops on FParser := TBufDatasetParser.Create(Self); which is inside TCustomBufDataset.ParseFilter.  I can never step into bufdataset_parser.pp. On the issue I'm chasing I'm completely lost, so I'm including way more information below in case someone has a suggestion. I'm trying to do this because I've got an "External SIGSEGV" exception that makes no sense to me.  I've got two ways of filtering a TBufDataset - one is populate the filter via a PopupMenu (filter string is the caption of the MenuItem).  The other is from a filter string built up from a UI.  BOTH ways set the filter in shared code, and every which way I try to look at it, the filter string is identical between the two cases.  I get the External SIGSEGV when I exit my app, but I only get it when I've used the PopupMenu... The exception is being raised inside BufDataset.pas, specifically, inside TCustomBufDataset.InternalClose on the line "if assigned(FParser) then FreeAndNil(FParser);"   By reading the code, I know that the FParser is a TBufDatasetParser.  Problem is I can't step inside that unit to try and get an idea of what's going on.  When I step into that line, I first go through FreeAndNil, then the exception is raised immediately on self.destroy in Tobject.Free; Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TObject.Free;         begin           // the call via self avoids a warning           if self<>nil then             self.destroy;        end; Here's my code for populating the filter: As far as the code below is concerned FDataset is just a TDataset. FFilterMRU is a TStringList.   I've been using this code for several years with no issue.  Previously I've been using DB aware datasets (both Zeos and SQLdb).  This is the first time I've used this code with BufDataset.  Looking at the code below, I can summarise my issue as: If I use btnShowFilterDlgClick to filter the Dataset - no excpetion is raised on exit.  If I use mnuSetFilterClick, then the exception is raised.  Both procedures actually call SETFILTER, which is where the filtering work is actually done. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Procedure TFrameGrid.mnuSetFilterClick(Sender: TObject);Var  sFilter: String;Begin  If FDataset.Active Then    If (Sender Is TMenuItem) Then    Begin      ClearFilter;       sFilter := FFilterMRU[TMenuItem(Sender).Tag];      SetFilter(sFilter, []);    End;End; Procedure TFrameGrid.btnShowFilterDlgClick(Sender: TObject);Var  oDlg: TdlgSQLFilter;Begin  If FDataset.Active Then  Begin    oDlg := TdlgSQLFilter.Create(Self);    Try      ClearFilter;       // Yeah, setting these two in seemingly wrong order, but intialise must be called after      // the dataset is attached, and Filter must be called after Initialisation...       oDlg.Dataset := FDataset;      oDlg.Initialise;      oDlg.Filter := FDataset.Filter;       If oDlg.ShowModal = mrOk Then        SetFilter(oDlg.Filter, oDlg.FilterOptions);    Finally      oDlg.Free;    End;  End;End; Procedure TFrameGrid.ClearFilter;Begin  SetFilter('', []);End; Procedure TFrameGrid.SetFilter(AFilter: String; AFilterOptions: TFilterOptions);Var  sFilter, sError: String;  iCurr: Integer;Begin  grdSQL.SelectedRows.Clear;   FDataset.DisableControls;  Try    sFilter := Trim(AFilter);    iCurr := FFilterMRU.IndexOf(sFilter);       // Ensure the latest Filter is pushed into the top of the list    // Also facilitates removing corrupt filters from the list    If iCurr > 0 Then      FFilterMRU.Delete(iCurr);     Try      // Try to apply the filter.    FDataset.FilterOptions := AFilterOptions;      FDataset.Filter := sFilter;      FDataset.Filtered := (sFilter <> '');    Except      On E: Exception Do      Begin        sError := 'Filter: ' + AFilter + LineEnding + LineEnding;        sError := sError + 'Error: ' + E.ClassName + LineEnding + LineEnding;        sError := sError + E.Message;         ShowMessage(sError);        sFilter := '';      End;    End;     If (iCurr <> 0) And (FDataset.Filtered) Then    Begin      FFilterMRU.Insert(0, sFilter);         // Lets keep the MRU sane...      If FFilterMRU.Count > 10 Then        FFilterMRU.Delete(FFilterMRU.Count - 1);    End;  Finally    FDataset.EnableControls;  End;   UpdateScrollbar;  SetFilterHint(sFilter);  RefreshUI;End;  My gut feeling is it's not the BufDatasetParser to blame.  I must be doing something wrong elsewhere, and my app is quite large.  Well, the framework I'm using is.  So I want to try to get an idea of what's going on inside BufDatasetParser to see if that gives me a clue as to what I'm doing wrong elsewhere.  I've also attached the dialog I'm using to build the Filter string. In short - help :-) ---------------------------------------------------------------------- wp · 2018-11-25 10:42 This is the way I would do it (maybe not the best one?): Go to "Project options" > "Additions and overrides". Click on "Stored in session" > "Add" > "Custom Option".  In the new line appearing under "Stored in session" > "Targets" > "Custom" type: "-gw2" (without quotes) - this will activate Dwarf2 debugger info for all needed units (You may try other -g* options, but I found -gw2 to work fine for me on Windows - you can find the available options in "Debugging" > "Type of debug info"). OK. In the Project Inspector, click on "Add" > "Add files from the file system". Navigate to the folder which contains the unit with TBufDataset (bafdataset.pas). Select the unit to add it to the project. Confirm the question to extend the search path. Compile. It may be that other units depend on the recompiled FCL units and cannot be found. When a corresponding message appears extend the search path again. Repeat until the entire project compiles.Now you can set a breakpoint inside the TBufDataset or TDataset code.Normally I am not a friend of adding units to the search path because of its possible complications. Therefore I'd recommend that you do this exercise with a backup copy of your project. Or you delete the added units from the project and search path when you are done, and also delete the ppu folder to get rid of the FCL units found here now. You can keep the "-gw2" because you can still step into the LCL units this way. Note, however, that the first recompilation of another project will take longer because the LCL has to be compiled again without debug info, and the same will happen when you load the debugged project again. ---------------------------------------------------------------------- Mike.Cornflake · 2018-11-25 23:45 Quote from: wp on November 25, 2018, 11:42:12 amGo to "Project options" > "Additions and overrides". Click on "Stored in session" > "Add" > "Custom Option".  In the new line appearing under "Stored in session" > "Targets" > "Custom" type: "-gw2" (without quotes) - this will activate Dwarf2 debugger info for all needed units (You may try other -g* options, but I found -gw2 to work fine for me on Windows - you can find the available options in "Debugging" > "Type of debug info"). OK. In the Project Inspector, click on "Add" > "Add files from the file system". Navigate to the folder which contains the unit with TBufDataset (bafdataset.pas). Select the unit to add it to the project. Confirm the question to extend the search path. Compile. It may be that other units depend on the recompiled FCL units and cannot be found. When a corresponding message appears extend the search path again. Repeat until the entire project compiles.Now you can set a breakpoint inside the TBufDataset or TDataset code. Awesome, I'm in!  Only needed to add bufdataset_parser.pp. I hear you about using a copy of my project.  In my case I'm using version control, and I will restore the project files when I've solved this Many thanks Mike