How te create a functions which returns a Query (or datasource) lazarus / 16-Databases ---------------------------------------------------------------------- Hansvb · 2022-06-17 11:57 Hi, I would like to create a function that returns a query (or a datasource). What I have so far is below. Main screen is under a temporary test button: 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 TFrm_Main.Button1Click(Sender: TObject);var  MaintainAppdatabase : TMaintainAppdatabase;  Query : TSQLQuery;  ds : tDataSource;begin  try    MaintainAppdatabase := TMaintainAppdatabase.Create();    Query := TSQLQuery.Create(nil);    Query :=  MaintainAppdatabase.SelectAllItems();  // Query gets empty.  <<-- this goes wrong SIGSEGV     ds := tDataSource.Create(nil);    ds.DataSet := Query;     DBGridMain.DataSource := ds;    if assigned(Query) then Query.Free;    ds.free;     MaintainAppdatabase.Free;  finally    // TODO;  end;end;       In a separate unit (MaintainAppdatabase) is the function that the query or data source should return. That is: 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 function TMaintainAppdatabase.SelectAllItems() : TSQLQuery;var  selectSql : String;  Query     : TSQLQuery;begin  selectSql := 'select * from ' + TableName.ITEMS;   try      SQLite3Conn.Close();      SQLite3Conn.DatabaseName := AppDatabaseFile;      SQLite3Conn.Open;    SQLTransaction.Active := True;       Query := TSQLQuery.Create(nil);      Query.SQL.Text := selectSql;      Query.DataBase := SQLite3Conn;      Query.Open;       ResultQuery :=  Query;  // ResultQuery is a TSQLQuery      Result := ResultQuery;     Query.Close;       SQLite3Conn.Close();      Query.Free;       SQLite3Conn.Close();    except      on E : Exception do        begin        Frm_Main.Logging.WriteToLogError('Fout opgetreden bij het lezen van de tabel ' + TableName.ITEMS);          Frm_Main.Logging.WriteToLogError(rsMessage);          Frm_Main.Logging.WriteToLogError(E.Message);        end;    end;end; Where am I going wrong? ---------------------------------------------------------------------- Zvoni · 2022-06-17 12:04 First codeblock, Line 9: Remove it ---------------------------------------------------------------------- Hansvb · 2022-06-17 12:18 When i remove that line then de SIGSEGV is gone. But the function is still wrong. Query gets empty in the second code block. Line 24 in the second code block is the problem. ---------------------------------------------------------------------- MarkMLl · 2022-06-17 12:40 Quote from: Hansvb on June 17, 2022, 02:18:57 pmWhen i remove that line then de SIGSEGV is gone. But the function is still wrong. Query gets empty in the second code block. Line 24 in the second code block is the problem. Because you've just freed whatever your result points to. MarkMLl ---------------------------------------------------------------------- Hansvb · 2022-06-17 12:49 I know. How can I avoid that or first make a copy? before I free the query. My workaround will be the use of a data module I think. ---------------------------------------------------------------------- MarkMLl · 2022-06-17 13:18 Quote from: Hansvb on June 17, 2022, 02:49:03 pmI know. How can I avoid that or first make a copy? before I free the query. My workaround will be the use of a data module I think. Assume you can't without opening a new query to the server. Having multiple references to the same object is, at best, perilous. MarkMLl ---------------------------------------------------------------------- Hansvb · 2022-06-17 13:28 I see. With a datamodule it works fine. I will use that. ---------------------------------------------------------------------- MarkMLl · 2022-06-17 14:13 Remember that there's no rule that says that a query (etc.) opened in a function has to be closed there, or that an object created in a function has to be freed there. The limit is whether you're confident that you understand the code that you're writing, and a part of that is properly documenting or at least commenting the behaviour of each function: i.e. something like "It's the caller's responsibility to close and free the TQuery created in this function". MarkMLl ---------------------------------------------------------------------- BrunoK · 2022-06-17 16:13 Quote from: Zvoni on June 17, 2022, 02:04:03 pmFirst codeblock, Line 9: Remove it that, and another likely problem is in Second codeblock you pass "Query" as the result; but that's only a reference copy to the "Query" created at line 14, then before returning, you free the "Result" instance at line 24 of 2nd block. You  may have an apparently valid function return, but that wont last long in the caller because the instance may have been altered due to recycling of the freed memory. ---------------------------------------------------------------------- MarkMLl · 2022-06-17 20:32 Quote from: BrunoK on June 17, 2022, 06:13:29 pmYou  may have an apparently valid function return, but that wont last long in the caller because the instance may have been altered due to recycling of the freed memory. I was going to point out that I said that hours ago, but you highlight an important issue: the data might look valid when first referenced, but then be overwritten unpredictably. And calling a method or writing to a property in an object that's already been freed is a recipe for disaster :-) And using FreeAndNil() is no solution if one's already copied the pointer that represents the object, because it will only nil the pointer that it's directly applied to rather than wiping the object itself. MarkMLl