Interestingly enough I asked now having a reasonable idea of the answer if āImage uses the secondary stack.
_______________________________________
Notebooklm grounded in the ARM stated that
_______________________________________
āBased on the sources, the term āsecondary stackā is not explicitly used in relation to the Image
attribute. However, the mechanism by which Image
functions operate, and certain implementation requirements, provide insight into their memory usage.
Specifically:
⢠The S'Image
attribute, along with S'Wide_Image
and S'Wide_Wide_Image
, functions by calling S'Put_Image
.
⢠The S'Put_Image
procedure typically stores a sequence of character values in a text buffer.
⢠After S'Put_Image
populates this buffer, the S'Image
function then retrieves the contents from that buffer using a Get
function (e.g., Get
for S'Image
, Wide_Get
for S'Wide_Image
, Wide_Wide_Get
for S'Wide_Wide_Image
).
Regarding memory allocation for this text buffer, the sources state:
⢠If a Max_Image_Length
restriction applies to any compilation unit in a partition, then S'Image
, S'Wide_Image
, and S'Wide_Wide_Image
shall be implemented without any dynamic allocation within that partition.
While the sources do not use the specific term āsecondary stack,ā the requirement to implement image attributes without dynamic allocation when the Max_Image_Length
restriction is in effect implies that the buffer used by S'Put_Image
would need to be allocated on the primary call stack of the executing task or in a statically allocated region of memory, rather than on the heap (which is typically what ādynamic allocationā refers to in this context).
General mentions of stack usage in the sources relate to:
⢠The Storage_Size
attribute for a task object, which denotes the number of storage elements reserved for the task, including the size of its stack.
⢠The possibility that objects created by allocators, when passed as actual parameters to an access parameter, may be allocated on the stack and automatically reclaimed.
⢠Requirements for implementations to document the minimum stack space necessary for interrupt handlers.
⢠Documentation requirements for reviewable programs to identify the length of fixed-size and non-fixed-size portions of memory reserved on a run-time stack for constructs like subprograms and tasks.
In summary, the sources indicate that S'Image
uses an internal text buffer, and under the Max_Image_Length
restriction, this buffer must avoid dynamic allocation. While the specific term āsecondary stackā is not used, this restriction suggests that the buffer would reside on a stack or in static memory if dynamic allocation is disallowed.ā
____________________________________________
CoPilot/ChatGPT came up with this including the incorrect statements like the light runtime does not have secondary stack support. Unbounded strings arenāt available for the user to use in the light runtime.
____________________________________________
In Ada, 'Image
is an attribute that produces a string representation of a value ā for example, Integer'Image(42)
yields " 42"
(note the leading space for positive numbers).
Whether 'Image
uses a secondary stack depends on your Ada implementation and runātime model, but in most modern GNATābased compilers:
-
'Image
is implemented as a function that returns a String
.
-
The compiler typically allocates that string in the secondary stack (also called the secondary storage pool) rather than the main call stack.
-
This is because the size of the string is determined at run time, and the secondary stack lets Ada handle variableālength temporaries without fixed frame allocations.
-
The exact mechanism can vary ā with optimizations, some small 'Image
results might be placed in registers or on the primary stack.
Why it matters:
If youāre working in an environment where the secondary stack is small or fragmented, heavy use of 'Image
(especially in loops or on large arrays) can cause stackāspace pressure. In those cases, you might want to:
-
Reuse a preallocated buffer and use 'Wide_Wide_Image
-like logic manually.
-
Convert values to strings via Ada.Text_IO
into an existing string or buffer.
-
Control secondary stack use with compiler switches (-gnatS
, -gnatD
, etc. in GNAT to inspect allocations).
If you let me know which Ada compiler or environment youāre using, I can give you more specific behaviour details for 'Image
in that context.
āAh, that changes things quite a bit. In the light runtime profile, Adaās runātime library is slimmed down ā which affects how 'Image
and other stringāproducing attributes are handled.
Hereās the key difference:
-
No secondary stack support:
The light runtime omits the usual secondary stack mechanism that the full GNAT runātime uses for unconstrained temporaries. That means 'Image
canāt quietly allocate a variableālength string there.
-
Static or heap allocation instead:
In this profile, 'Image
typically allocates the return string on the heap via Ada.Strings.Unbounded
āstyle routines, or uses static buffers inside generated code if the maximum size is known at compileātime (e.g., for fixedārange discrete types).
-
Implication for your code:
-
You wonāt hit secondary stack exhaustion, but you can incur dynamic heap allocations every time you call 'Image
.
-
On small or embedded targets, that can create heapāfragmentation risks or latency spikes.
-
If deterministic memory usage is important, youāll want to avoid repeated 'Image
calls in tight loops, and instead reuse preallocated buffers.
Possible workarounds in light runtime:
-
Use Ada.Text_IO
into a preāallocated buffer.
-
Implement a custom integerātoāstring or enumerationātoāstring conversion that writes directly into an existing array.
-
Profile memory usage ā heap use is your main pressure point here.
If you tell me which target/board youāre compiling for, I can suggest patterns that completely avoid heap allocation in the light profile.ā