I want to write an application for DOS using small code/data model, but I would like to use far pointers for some selected memory blocks. I would like to use the OpenWatcom C++/16 compiler.
So, for most of the things I would like to have near pointers, but one array in the program I'd like to store using a far pointer, because it's big, accessed rarely, and I don't want to pollute my near heap with this large blob.
Normally I'm allocating the memory using malloc()
, and this produces normal near pointers to my data from the "near" heap. For the larger array, I'd like to use _fmalloc()
to allocate the data from the "far" heap.
Question number 1: Is it possible to mix malloc()
and _fmalloc()
in the same program using small memory data model?
I'm having doubts if that's possible, because the Watcom docs have this comment in clib.pdf:
The _nheapgrow function attempts to grow the near heap to the maximum size of 64K. You will want to do this in the small data models if you are using both malloc and _fmalloc or halloc. Once a call to _fmalloc or halloc has been made, you may not be able to allocate any memory with malloc unless space has been reserved for the near heap using either malloc, sbrk or _nheapgrow.
So I happily call _nheapgrow()
on the beginning of my program:
int main() {
_nheapgrow();
uint8_t far* ptr = (uint8_t*) _fmalloc(20);
printf("ptr: %08lX\n", ptr);
ptr[0] = 0;
return 0;
}
The problem is that the call to _fmalloc()
now returns a memory location which seems to overlap with other allocated memory blocks in the near heap (and the application data). In this example, it overwrites the "NULL pointer protection area", a 0x20-sized memory block filled with 0x01's which is supposed to guard against null pointer dereferences. This is reported as:
Question number 2: is this normal behavior, or is it a bug in the stdlib?
When switching to large data memory model, everything seems to be fine, since "near" heap isn't used at all (I think). Everything is aliased to _fmalloc()
, _ffree()
, etc, and the "near" variants are never called.
So in order to use _fmalloc()
, am I forced to switch to large data memory model?
(uint8_t*)
and not to(uint8_t far*)
.typedef
to name types and give you a bit more protection - not protection form the compiler - that won't help with a cast - but protection when you're writing/reading your code.