Search code examples
cmallocdosmemory-modelturbo-c

TurboC - malloc() in "compact" memory model


I am using good old Borland's TurboC compiler for DOS. When I use malloc() on compact memory model and write anything to the allocated memory, program freezes at some point (I suspect malloc() returns pointer to somewhere I shouldn't write). When I do the same on small memory model, it works fine.

I took a look on the allocated memory and the pointer the malloc() returns, using this small piece of code:

#include <stdio.h>

unsigned char *x;
unsigned int i;
unsigned int mds, mss;

#define X(a) x[i+(a)]

int main(void) {

    // show current SS and DS
    asm {
        mov AX, DS
        mov mds, AX
        mov AX, SS
        mov mss, AX
    }
    printf("ds=%04x, ss=%04x\n", mds, mss);

    // allocate memory and show the pointer
    x = (unsigned char*)malloc(128);
    printf("x=%p\n", x);

    // write out contents of the allocated memory
    for (i = 0; i < 128; i += 16)
        printf("%p: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", &x[i], X(0), X(1), X(2), X(3), X(4), X(5), X(6), X(7), X(8), X(9), X(10), X(11), X(12), X(13), X(14), X(15));

    free(x);
    return 0;
}

When I compile this for small memory model, I get:

tcc -ms -IC:\turboc\include -LC:\turboc\lib -etest.exe test.c

ds=02f9, ss=02f9
x=05f2
05f2: 00 00 00 ... 00
0602: 00 00 00 ... 00
...
0662: 00 00 00 ... 00

When I do the same with compact memory model, I get:

tcc -mc -IC:\turboc\include -LC:\turboc\lib -etest.exe test.c

ds=034f, ss=0391
x=0000:0004
0000:0004: 08 00 70 00 ... 08 00 70 00
0000:0014: 54 ff 00 f0 ... a5 fe 00 f0
...
0000:0074: a4 f0 00 f0 ... 60 14 00 f0

The pointer 0000:0004 looks suspicious to me and I suspect it to point somewhere outside the heap. I do not recognize the contents, but if I write to the memory, the program freezes.

What am I doing wrong and what should I do to get correct pointer from malloc()? Any suggestion will be appreciated.


Solution

  • According to an old reference manual, including <stdlib.h> should fix this. (Compilers on other systems would print a warning for this code, too.)

    Without a prototype, malloc is implicitly declared as returning int. The returned int value is automatically converted to a pointer. But in the compact memory model, pointers and ints do not have the same representation, so the implicit declaration and conversion do not yield the correct value.

    Pretty much same thing happens with implicitly declared malloc on 64-bit UNIX-like platforms.