Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3604552
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T21:00:44+00:00 2026-05-18T21:00:44+00:00

Env: Delphi 2007 <Justification>I tend to use complex records quite frequently as they offer

  • 0

Env: Delphi 2007

<Justification>I tend to use complex records quite frequently as they offer almost all of the advantages of classes but with much simpler handling.</Justification>

Anyhoo, one particularly complex record I have just implemented is trashing memory (later leading to an “Invalid Pointer Operation” error).

This is an example of the memory trashing code:

sSignature := gProfiles.Profile[_stPrimary].Signature.Formatted(True);

On the second time i call it i get “Invalid Pointer Operation”

It works OK if i call it like this:

  AProfile    := gProfiles.Profile[_stPrimary];
  ASignature  := AProfile.Signature;
  sSignature  := ASignature.Formatted(True);

Background Code:

  gProfiles: TProfiles;

  TProfiles = Record
  private
    FPrimaryProfileID: Integer;
    FCachedProfile: TProfile;
    ...
  public
    < much code removed >

    property Profile[ProfileType: TProfileType]: TProfile Read GetProfile;
  end;


  function TProfiles.GetProfile(ProfileType: TProfileType): TProfile;
  begin        
    case ProfileType of
      _stPrimary        : Result := ProfileByID(FPrimaryProfileID);
      ...
    end;
  end;

  function TProfiles.ProfileByID(iID: Integer): TProfile;
  begin
    <snip>
    if LoadProfileOfID(iID, FCachedProfile)  then
    begin
      Result := FCachedProfile;
    end
    else
    ...
  end;


  TProfile = Record
  private     
    ...
  public
    ...
    Signature: TSignature;
    ...
  end;


  TSignature = Record
  private               
  public
    PlainTextFormat : string;
    HTMLFormat      : string;

    // The text to insert into a message when using this profile
    function Formatted(bHTML: boolean): string;
  end;

  function TSignature.Formatted(bHTML: boolean): string;
  begin
    if bHTML then
      result := HTMLFormat
    else
      result := PlainTextFormat;
    < SNIP MUCH CODE >
  end;

OK, so I have a record within a record within a record, which is approaching Inception level confusion and I’m the first to admit is not really a good model. Clearly i am going to have to restructure it. What I would like from you gurus is a better understanding of why it is trashing the memory (something to do with the string object that is created then freed…) so that i can avoid making these kinds of errors in future.

Thanks

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T21:00:45+00:00Added an answer on May 18, 2026 at 9:00 pm

    Your justification for using records over classes seems flawed. Every time you return a record as a function result or pass a record as a function parameter or assign from one record var to another record var, all the fields of that record structure are being copied in memory.

    This alone can be cause for concern. Compared to reference types, passing record type variables around can suck the life out of a program. Your code could easily spend more time copying stuff from here to there and there to here than on actually getting work done.

    The difference between calling your three functions in series in one statement versus calling the three functions in separate statements is the allocation and lifetime of the intermediate results. When you call the functions in separate statements, you provide local variables to hold the intermediate results between calls. The variables are explicit and their lifetimes are well defined.

    When you call the functions in one statement, the compiler is responsible for allocating temporary variables to hold the intermediate results between calls. Lifetime analysis of these implicit variables can become murky – can the same local variable be used to hold the intermediate results of multiple calls in series? Most of the time, the answer is probably yes, but if the record types involved contain fields of compiler-managed data types (strings, variants, and interfaces) the same local variable can’t just be overwritten with the next block of data.

    Records containing compiler-managed types must be disposed of in an orderly fashion to avoid leaking heap memory. If such a record is overwritten with garbage data, or if such a record is copied without the compiler’s awareness, then the compiler generated code to dispose of the compiler-managed fields of the record when the record goes out of scope will likely report that it encountered an invalid pointer and/or a corrupt heap.

    Your TSignature record contains string fields, making it a compiler-managed data type. Everywhere that you have a local variable of type TSignature, the compiler has to implicitly generate try..finally frames in the body of the function to make sure the string fields in that local variable structure get released when execution leaves that scope.

    Any operation that ends up modifying or overwriting the string field pointers in the TSignature record can lead to an Invalid Pointer Operation error. Making copies of the record (by assigning it to multiple variables) should increment the ref counts automatically, but any use of MemCopy to bulk copy the record’s contents to some other location will throw off the ref counts and lead to Invalid Pointer Operation when the cleanup code tries to release those string fields more times than they were actually referenced. Typecasting a record variable to the wrong record type could cause the string fields to be overwritten with garbage, and cause an Invalid Pointer Operation down the line (when the record is cleaned up at the end of the scope)

    There is also a possibilty that the compiler itself has lost track of the intermediate record variables in the single-statement scenario and is cleaning up the hidden intermediates too many times or overwriting them without cleaning up the prior values. There was a compiler bug in this area somewhere back in the Delphi 3 era, but I don’t recall which product release we fixed it in. I seem to recall the bug I have in mind involved record type function results being passed to const type parameters, so it’s not an exact match to your scenario, but the consequences are similar.

    Before reporting this as a compiler bug, go over your code with a fine-toothed comb in the debugger disassembly view. There are tons of ways you can screw this up all by yourself. See where the intermediate results are being allocated, written to, and disposed by the compiler-generated code, and how your code is interacting with that pattern.

    The smoking gun will be when you see the string fields of one temp record variable overwritten without a call to decrement the reference to those strings. It could be caused by your code, or it could be caused by something in the compiler generated code, but the only way to find out is to witness the act and work out the finger pointing from there.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

#!/usr/bin/env perl use warnings; use strict; use Excel::Writer::XLSX; my $workbook = Excel::Writer::XLSX->new( 'perl.xlsx' );
I can't access env variables in the Rails console, while in the application they
!/usr/bin/env perl use warnings; use strict; my $text = 'hello ' x 30; printf
Env: jQuery, richfaces, all major browsers How to disable printing options in the browser
#!/usr/bin/env perl use warnings; use 5.014; use Term::Cap; use POSIX; my $termios = new
Env.: VS2008 C# project I need to build my app for use in 2
why cannot I use @env['REMOTE_ADDR'] outside a route in Sinatra? I want to have
#!/usr/bin/env perl use warnings; use 5.012; use utf8; use WWW::Mechanize::Cached; use Some::Module qw(some_method); my
Env.: .NET4 C# Hi All, I want to combine these 2 lists : {
In my local dev env, I use PHP Version 5.3.3-1ubuntu9.2. Now when I see

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.