Set the parent with the constructor. (form or Panel) Don't create with nil. E.g. some messages go to the parent window before they go to the buttons, so if the parent is not set you will miss those.
Also highly likely to cause memory leaks if you forget to manually free them. If the parent /owner is known that will take care of cleaning up the controls when it is destroyed.
I see you set the parent, but this is not really the owner. If you do TButton.Create(MainForm); that will be done for you.
Note the difference:
"The Parent property declared in TControl is similar to the Owner property declared in TComponent, in that the Parent of a control frees the control just as the Owner of a component frees that Component. However, the Parent of a control is always a windowed control that visually contains the control, and is responsible for writing the control to a stream when the form is saved. The Owner of a component is the component that was passed as a parameter in the constructor and, if assigned, initiates the process of saving all objects (including the control and its parent) when the form is saved."
This is from the Delphi docs, but the same holds true for Freepascal and Lazarus. And the constructor does more afaik, so try this first:
RoundButtons[x]:=TButton.create(mainform);
// and leave this out RoundButtons[x].parent:= MainForm;
And more importantly (and a possible cause of a SIGSEV):
dynamic arrays count from zero and you set from one so you are running the risk of over-indexing the array by one........ (Although you use high() zero is empty. Should be:
Setlength(RoundButtons, NumberOfRounds);
For x:= 0 to High(NumberOfRounds) do