-1

I get an AccessViolation when running the following simple code with Delphi XE5:

Access violation at 0x0040213c: write of address 0x00000000

This runs without any problems with Delphi 2009! What has changed since than?!

program consola;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.Classes;

type
  MyRecord = Record
    name : string;
    age  : Integer;
  end;

var
  recPointer : ^MyRecord;
  FList: PPointerList;

begin
  New(recPointer);
  recPointer.name := 'Brian';
  recPointer.age  := 23;

  GetMem(FList, 4 * SizeOf(recPointer));

  FList^[0] := recPointer;
end.

2 Answers2

2

Have you seen declaration of PPointerList on XE5? This is pointer to dynamic array now

Extract from help:

Delphi type PPointerList = ^TPointerList;
Delphi type TPointerList = array of Pointer;

so possible usage is:

  New(Flist);
  SetLength(Flist^, 4);

  FList^[0] := recPointer;

(of course, PPointerList is useless here, it's enough to exploit TPointerList)

MBo
  • 77,366
  • 5
  • 53
  • 86
  • Even `TPointerList` is pretty much useless here. It forces you to do memory management by hand and handle the fact that the record has managed members. New and Dispose and lots of furkling. – David Heffernan May 26 '14 at 14:21
  • Ok, maybe my example is not the best, I just try to create a small example based on a real problem I have in my code. In the real problem, instead of the Record, I have a class. Before it was: `PPointerList = ^TPointerList; TPointerList = array[0..MaxListSize - 1] of Pointer;`, so what is the difference??! – Tiberiu Popa May 27 '14 at 06:58
  • Old declaration uses pointer to static array, new declaration - pointer to dynamic array, which have special memory layout, automatic life cycle management etc. Note I've use SetLength routine instead of GetMem etc. I think you have to sound your real problem, not your (possibly wrong) method to solve it. Probably, modern-style approaches (like proposed by David), will more flexible and safe. – MBo May 27 '14 at 07:23
  • @user3676483 I don't understand why you want to do all the memory allocation yourself. You are making life far harder than it needs to be? Why would you choose to do that? – David Heffernan May 27 '14 at 09:56
2

You are using the wrong types here. Your FList variable is a pointer to a dynamic array of untyped pointers. That is not what you need at all. And you don't allocate the memory properly. I'm not going to try to explain more about your code because your current approach is fundamentally flawed.

You should use either a dynamic array or TList<MyRecord>. The former looks like this:

var
  Arr: TArray<MyRecord>;
....
SetLength(Arr, 4);
Arr[0].Name := ...

And the latter:

var
  List: TList<MyRecord>;
  Rec: MyRecord;
....
List := TList<MyRecord>.Create;
Rec.Name := ...
List.Add(Rec);

Your code is a recipe for disaster. Even if you fix the types to allow you to allocate using GetMem, how are you going to handle management of the managed string member of your record. Make life easy by using type safe data structures and so allow the compiler to do the heavy lifting.

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490