DOS Objects Lifecycle

Several AmigaDOS objects have hidden elements beyond what the public struct declaration shows. sizeof() therefore does not describe the real allocation size, and a hand-rolled AllocMem() can leave the object in a state that the rest of dos.library rejects or crashes on. For these objects, dos.library provides a constructor–destructor pair:

APTR  AllocDosObject(ULONG type, struct TagItem *tags);    /* V36 */
APTR  AllocDosObjectTagList(ULONG type, struct TagItem *tags);
APTR  AllocDosObjectTags(ULONG type, ULONG tag1, ...);
void  FreeDosObject(ULONG type, APTR ptr);                 /* V36 */

All three constructors share one entry point. AllocDosObjectTags() accepts a variadic tag list terminated by TAG_DONE.

Object types

Defined in dos/dos.h. The list changes over releases — the table below is V36+.

Type Object Hidden elements? Notes
DOS_FILEHANDLE 2.0+ struct FileHandle Yes Never hand-allocate. The tag ADO_FH_Mode is accepted but currently unused.
DOS_EXALLCONTROL 2.0+ struct ExAllControl Yes Must be allocated with AllocDosObject().
DOS_FIB 2.0+ struct FileInfoBlock No Long-word alignment required; use D_S() on the stack.
DOS_STDPKT 2.0+ struct StandardPacket No, but a layout quirk Returned pointer is to the inner DosPacket, not the StandardPacket.
DOS_CLI 2.0+ struct CommandLineInterface Yes (V47+) Manual construction no longer works as of V47; the Shell needs the private elements.
DOS_RDARGS 2.0+ struct RDArgs No Use this for custom ReadArgs() flows over alternative inputs.

DOS_FILEHANDLE

Used for Open()-style file handles. ADO_FH_Mode (from dos/dostags.h) takes one of the values from MODE_OLDFILE / MODE_NEWFILE / MODE_READWRITE. The autodoc implies it controls handle initialization, but the current implementation ignores it; do not rely on a particular mode after AllocDosObject().

DOS_STDPKT

Aggregates an exec Message and a DosPacket with the linkage fields (sp_Msg.mn_Node, sp_Pkt.dp_Link, sp_Pkt.dp_Port) pre-wired. AllocDosObject(DOS_STDPKT, NULL) returns the address of the inner DosPacket (&sp_Pkt), not the outer StandardPacket. Pass that pointer to SendPkt() and to FreeDosObject().

If you construct the structure yourself, ensure the DosPacket is longword-aligned and link mn_Node of the message and dp_Link of the packet to each other.

DOS_CLI

Constructed with optional tag list:

Tag Effect
ADO_PromptLen 2.0+ Size in bytes of cli_Prompt
ADO_CommNameLen 2.0+ Size in bytes of cli_CommandName
ADO_CommFileLen 2.0+ Size in bytes of cli_CommandFile
ADO_DirLen 2.0+ Size in bytes of cli_SetName

None of these tags are useful in practice — the V47 Shell uses hard-coded limits rather than the field sizes. Allocate with TAG_DONE for normal use.

V47+: do not construct struct CLI manually. It contains private elements that the Shell relies on; missing them yields a degraded shell. Always go through AllocDosObject().

FreeDosObject — releasing an object

void FreeDosObject(ULONG type, APTR ptr);

Destroys the object and releases its resources. Pass ptr = NULL to perform a no-op (handy for cleanup paths). The type argument must match what was passed to AllocDosObject().

For DOS_STDPKT, ptr is the address of the inner DosPacket, not the outer StandardPacket.

FreeDosObject() does not touch IoErr().

Memory leak in old releases

FreeDosObject(DOS_CLI, …) on AmigaDOS V37 and earlier did not free all buffers associated with the CLI structure. The leak was fixed in V39. If you must support pre-V39, free cli_Prompt, cli_CommandName, cli_CommandFile, and cli_SetName manually before calling FreeDosObject().

Worked example

#include <dos/dos.h>
#include <dos/dostags.h>

struct ExAllControl *MakeExAllControl(void)
{
    return (struct ExAllControl *)AllocDosObject(DOS_EXALLCONTROL, NULL);
}

void DisposeExAllControl(struct ExAllControl *eac)
{
    FreeDosObject(DOS_EXALLCONTROL, eac);
}

/* Sending a packet to a handler using AllocDosObject. */
struct MsgPort       *port;          /* target handler port */
struct DosPacket     *pkt;

pkt = (struct DosPacket *)AllocDosObject(DOS_STDPKT, NULL);
if (pkt) {
    pkt->dp_Type = ACTION_CURRENT_VOLUME;
    pkt->dp_Arg1 = 0;
    SendPkt(pkt, port);
    WaitPkt();   /* or WaitPort(port) then GetMsg() */
    /* ...use dp_Res1/dp_Res2... */
    FreeDosObject(DOS_STDPKT, pkt);
}

See Also


Sources: Thomas Richter, "ROM Kernel Reference Manual: AmigaDOS" (First Edition, 2024), Chapter 16.1 — Object Constructors and Destructors. Raw: raw/rkm/rkm-dos-book.md Updated: 2026-10-02