How can I set a custom stack size in TThread
? I am trying to reintroduce the constructor of TThread
but it says that ThreadProc
is missing yet its right there in System.Classes
.
type
TThreadHelper = class helper for TThread
constructor Create(const CreateSuspended: Boolean = False; const StackSize: Integer = 0); reintroduce;
end;
{ TThreadHelper }
constructor TThreadHelper.Create(const CreateSuspended: Boolean; const StackSize: Integer);
begin
Self.FSuspended := not Self.FExternalThread;
Self.FCreateSuspended := CreateSuspended and not Self.FExternalThread;
if not Self.FExternalThread then
begin
Self.FHandle := BeginThread(nil, StackSize, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, Self.FThreadID);
if Self.FHandle = 0 then
raise EThread.CreateResFmt(@SThreadCreateError, [SysErrorMessage(GetLastError)]);
end
else
begin
Self.FHandle := Winapi.Windows.GetCurrentThread;
Self.FThreadId := GetCurrentThreadId;
end;
end;
[dcc32 Error] Project5.dpr(29): E2003 Undeclared identifier: 'ThreadProc'
You may need to increase the stack size if your program gets stack-overflow messages at runtime. You can also set the stack size by: Using the /STACK linker option. For more information, see /STACK (Stack allocations).
CPP. size() function is used to return the size of the stack container or the number of elements in the stack container. Syntax : stackname.
Default Stack Size for JVM Internal Threads The default system stack size is 256 KB on all platforms.
I do not know, if you can set stack size after a thread is created. Maybe SetThreadStackGuarantee
can be helpful?
You can create a thread from scratch by using BeginThread
, but it is quite complicated. I have here a workaround by using Detours
. Note that there are several Detours
variants. I think only the Cromis.Detours
is x64 compatible.
unit IndividualStackSizeForThread;
interface
uses
System.Classes,
Cromis.Detours { http://www.cromis.net/blog/downloads/cromis-ipc/ };
type
TThreadHelper = class helper for TThread
constructor Create(CreateSuspended: Boolean; StackSize: LongWord);
end;
implementation
var
TrampolineBeginThread: function(SecurityAttributes: Pointer; StackSize: LongWord;
ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
var ThreadId: TThreadID): THandle = nil;
threadvar
StackSizeOverride: LongWord;
function InterceptBeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
var ThreadId: TThreadID): THandle;
const
STACK_SIZE_PARAM_IS_A_RESERVATION = $00010000; // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx
begin
if StackSizeOverride <> 0 then
begin
CreationFlags := CreationFlags or STACK_SIZE_PARAM_IS_A_RESERVATION;
StackSize := StackSizeOverride;
StackSizeOverride := 0;
end;
Result := TrampolineBeginThread(SecurityAttributes, StackSize, ThreadFunc,
Parameter, CreationFlags, ThreadId);
end;
constructor TThreadHelper.Create(CreateSuspended: Boolean; StackSize: LongWord);
begin
StackSizeOverride := StackSize;
inherited Create(CreateSuspended);
end;
initialization
TrampolineBeginThread := InterceptCreate(@BeginThread, @InterceptBeginThread);
finalization
InterceptRemove(@TrampolineBeginThread, @InterceptBeginThread);
end.
I do not know why Embt does not allow programmer to specify the stack size, if someone knows the reason, it will be very interesting to me.
There is simply no way to control the stack size using TThread
. For whatever reason, the designers of TThread
failed to include a stack size parameter in the constructor of TThread
. This is clearly an omission. You should call BeginThread
or CreateThread
directly.
If you are simply desperate to make your hack work then you'll need to find the address of the ThreadProc
function declared in the implementation section of the Classes
unit. Some possible approaches:
TThread.Create
at runtime to read out the address of ThreadProc
.ThreadProc
.BeginThread
using a detour. Create a dummy thread. Note the address of the thread procedure passed. That is ThreadProc
.A good source of ideas for this sort of hacking is the source code for madExcept
.
Another way to apply the hack would again be to use a detour on BeginThread
. You could then use a thread local variable to supply the stack size. A value of high(LongWord)
for that thread local variable would mean "use the value passed as a parameter", and any other value would be the value used by the detoured BeginThread
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With