INF: printf() and 512-Byte I/O Buffer

ID Number: Q44725

5.10 6.00 6.00a 6.00ax 7.00 | 5.10 6.00 6.00a

MS-DOS | OS/2

Summary:

In Microsoft C versions 6.0, 6.0a, 6.0ax; C/C++ version 7.0; and

Microsoft QuickC versions 2.0 and 2.5, the function printf() takes up

512 bytes from the near heap (in small and medium memory model).

Microsoft C version 5.1 and QuickC version 1.01 do not take up any

memory.

More Information:

In current versions of C and QuickC, the standard I/O buffer gets

allocated only when needed. This gives the program an extra 512 bytes

of near heap space in small and medium memory models or an extra 512

bytes of far heap space in compact and large models. Therefore, when

the printf() function is used for the first time, a 512-byte buffer is

reserved for I/O, and the subsequent calls to printf() use that

buffer.

In C 5.1 and QuickC 1.01, a 512-byte buffer is always reserved at

startup. It doesn't matter if the program uses standard I/O or not.

The buffer is also always allocated in the near heap, no matter what

memory model is used.

The sample program below prints the amount of space left in the near

heap. When complied under C 5.1 or QuickC 1.01, the number is the same

before and after the execution of printf().

The program also uses _fheapwalk to show that C 5.1 and QuickC 1.01

always allocate the buffer in the near heap in any memory model, and

current versions allocate it in the near or far heap according to the

memory model.

When compiled under current versions, the number printed after the

printf() function is executed is 512 bytes fewer than the number

printed before the execution of printf().

Sample Code

-----------

/* Compile options needed: none

*/

#include <stdio.h>

#include <math.h>

#include <dos.h>

#include <malloc.h>

void heapdump (void);

void main (void)

{

unsigned n1, n2;

n1 = _memavl();

heapdump();

printf("first printf has been executed\n");

n2 = _memavl();

printf("space left in the near heap before printf %u\n",n1);

printf("space left in the near heap after printf %u\n",n2);

heapdump();

}

void heapdump (void)

{

struct _heapinfo hinfo;

int heapstatus;

hinfo._pentry = NULL;

while ((heapstatus = _fheapwalk(&hinfo)) == _HEAPOK)

{

printf("%6s block at %p of size %d in the far heap\n",

(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),

hinfo._pentry, hinfo._size);

}

switch (heapstatus)

{

case _HEAPEMPTY:

printf("OK - empty far heap\n");

break;

case _HEAPEND:

printf("OK - end of far heap\n");

break;

case _HEAPBADPTR:

printf("ERROR - bad pointer\n");

break;

case _HEAPBADBEGIN:

printf("ERROR - bad start\n");

break;

case _HEAPBADNODE:

printf("ERROR - bad node\n");

break;

}

}

Additional reference words: 2.00 2.50 5.00 5.10 6.00 6.00a 6.00ax 7.00

malloc()200 hex heapwalk