EmbeddedRelated.com
Forums
The 2026 Embedded Online Conference

Allocate dynamic memory Borland C++ 4.5

Started by srao June 22, 2016
I work on a legacy code with a borland C++ compiler. The processor is an
Intel 80C186EB. Has an external Flash of 1MB - which has 256K of RAM. 

I am trying to dynamically allocate 64K(Size = 0x10000 = 65536 bytes) of
memory from RAM but looks like allocation is successful only for (0xFFFF =
65535 bytes). 

I tried to use a huge pointer - 
>Byte __huge *pHugeDataBuffer = new (Byte __huge*)[65536L]; //returns NULL
>Byte __huge *hptr1; >Byte __huge *hptr2 = hptr1 + 65536; //successful
I was only able to increment an address pointed by this huge pointer. Could someone point me in the right direction? --------------------------------------- Posted through http://www.EmbeddedRelated.com
On Wed, 22 Jun 2016 18:22:28 -0500, srao wrote:

> I work on a legacy code with a borland C++ compiler. The processor is an > Intel 80C186EB. Has an external Flash of 1MB - which has 256K of RAM. > > I am trying to dynamically allocate 64K(Size = 0x10000 = 65536 bytes) of > memory from RAM but looks like allocation is successful only for (0xFFFF > = > 65535 bytes). > > I tried to use a huge pointer - >>Byte __huge *pHugeDataBuffer = new (Byte __huge*)[65536L]; //returns >>NULL > > >>Byte __huge *hptr1; >>Byte __huge *hptr2 = hptr1 + 65536; //successful > > I was only able to increment an address pointed by this huge pointer. > Could someone point me in the right direction? > --------------------------------------- > Posted through http://www.EmbeddedRelated.com
I will put aside the reason _why_ you want to allocate memory in an embedded system -- usually this is a Bad Idea, so expect someone (maybe me, if I get time) to question you closely on what you're trying to do, and why. I'm pretty sure that the memory allocation only works up to 65536. This is consistent with the limitations of Borland under DOS (and, perhaps, of DOS itself). Remember that the 80186 is pretty much a 16-bit processor with a strange memory paging scheme. So it's really easy to write a memory allocator that only works on blocks up to 2^16. I suspect that you're going to have to make your own memory allocator. You could test this by dredging through the header files ("new.h" is, I think, the one you want to look for) and see what the argument is to the default new [] operator. I suspect that it'll be of type int, which means that 65536 turns to zero. You can do the same thing for malloc -- if it takes a 16-bit integer, then the memory system simply cannot allocate more. Assuming that there isn't a "huge_malloc" (or something) already, you'll probably have to make one -- and you'll have to make a "malloc" and a "free" to go along with it. Then, to add insult to injury, if my suspicions are correct you won't be able to use new [] _at all_, and will, instead, have to do it the old fashioned way. On the plus side, there's plenty of nice memory allocators out there, so you don't have to be on your own. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com I'm looking for work -- see my website!
On 2016-06-22, Tim Wescott <seemywebsite@myfooter.really> wrote:
> On Wed, 22 Jun 2016 18:22:28 -0500, srao wrote: > >> I work on a legacy code with a borland C++ compiler. The processor is an >> Intel 80C186EB. Has an external Flash of 1MB - which has 256K of RAM. >> >> I am trying to dynamically allocate 64K(Size = 0x10000 = 65536 bytes) of >> memory from RAM but looks like allocation is successful only for (0xFFFF >> = >> 65535 bytes). >> >> I tried to use a huge pointer - >>>Byte __huge *pHugeDataBuffer = new (Byte __huge*)[65536L]; //returns >>>NULL >> >> >>>Byte __huge *hptr1; >>>Byte __huge *hptr2 = hptr1 + 65536; //successful >> >> I was only able to increment an address pointed by this huge pointer. >> Could someone point me in the right direction? >> --------------------------------------- >> Posted through http://www.EmbeddedRelated.com > > snip > I'm pretty sure that the memory allocation only works up to 65536. This > is consistent with the limitations of Borland under DOS (and, perhaps, of > DOS itself). Remember that the 80186 is pretty much a 16-bit processor > with a strange memory paging scheme. So it's really easy to write a > memory allocator that only works on blocks up to 2^16. > > I suspect that you're going to have to make your own memory allocator. > You could test this by dredging through the header files ("new.h" is, I > think, the one you want to look for) and see what the argument is to the > default new [] operator. I suspect that it'll be of type int, which > means that 65536 turns to zero. You can do the same thing for malloc -- > if it takes a 16-bit integer, then the memory system simply cannot > allocate more. > > Assuming that there isn't a "huge_malloc" (or something) already, you'll > probably have to make one -- and you'll have to make a "malloc" and a > "free" to go along with it. Then, to add insult to injury, if my > suspicions are correct you won't be able to use new [] _at all_, and > will, instead, have to do it the old fashioned way. > > On the plus side, there's plenty of nice memory allocators out there, so > you don't have to be on your own. >
I think you are going to be hosed by the 64k segmentation limit even if you do write a memory allocator that can get you more than the 64K - in multiple bytes. There are int86 calls that deal with this, I had many reboots trying to use them many years ago. Get a hold of the old "Programmers PC Sourcebook", this lists all the int86 calls. I think this is going to be hard row to hoe. Good Luck, Mike -- Mike McGinn KD2CNU "More kidneys than eyes."
On Thu, 23 Jun 2016 02:18:33 +0000, Mike McGinn wrote:

> On 2016-06-22, Tim Wescott <seemywebsite@myfooter.really> wrote: >> On Wed, 22 Jun 2016 18:22:28 -0500, srao wrote: >> >>> I work on a legacy code with a borland C++ compiler. The processor is >>> an Intel 80C186EB. Has an external Flash of 1MB - which has 256K of >>> RAM. >>> >>> I am trying to dynamically allocate 64K(Size = 0x10000 = 65536 bytes) >>> of memory from RAM but looks like allocation is successful only for >>> (0xFFFF = >>> 65535 bytes). >>> >>> I tried to use a huge pointer - >>>>Byte __huge *pHugeDataBuffer = new (Byte __huge*)[65536L]; //returns >>>>NULL >>> >>> >>>>Byte __huge *hptr1; >>>>Byte __huge *hptr2 = hptr1 + 65536; //successful >>> >>> I was only able to increment an address pointed by this huge pointer. >>> Could someone point me in the right direction? >>> --------------------------------------- >>> Posted through http://www.EmbeddedRelated.com >> >> snip >> I'm pretty sure that the memory allocation only works up to 65536. >> This is consistent with the limitations of Borland under DOS (and, >> perhaps, of DOS itself). Remember that the 80186 is pretty much a >> 16-bit processor with a strange memory paging scheme. So it's really >> easy to write a memory allocator that only works on blocks up to 2^16. >> >> I suspect that you're going to have to make your own memory allocator. >> You could test this by dredging through the header files ("new.h" is, I >> think, the one you want to look for) and see what the argument is to >> the default new [] operator. I suspect that it'll be of type int, >> which means that 65536 turns to zero. You can do the same thing for >> malloc -- if it takes a 16-bit integer, then the memory system simply >> cannot allocate more. >> >> Assuming that there isn't a "huge_malloc" (or something) already, >> you'll probably have to make one -- and you'll have to make a "malloc" >> and a "free" to go along with it. Then, to add insult to injury, if my >> suspicions are correct you won't be able to use new [] _at all_, and >> will, instead, have to do it the old fashioned way. >> >> On the plus side, there's plenty of nice memory allocators out there, >> so you don't have to be on your own. >> >> > I think you are going to be hosed by the 64k segmentation limit even if > you do write a memory allocator that can get you more than the 64K - in > multiple bytes. There are int86 calls that deal with this, I had many > reboots trying to use them many years ago. Get a hold of the old > "Programmers PC Sourcebook", this lists all the int86 calls. > > I think this is going to be hard row to hoe. > > Good Luck, > Mike
I don't think a "PC Sourcebook" is going to have much relevance to an 80186-based system. I doubt there's a DOS there. -- Tim Wescott Control systems, embedded software and circuit design I'm looking for work! See my website if you're interested http://www.wescottdesign.com
On Wed, 22 Jun 2016 18:22:28 -0500, "srao" <109468@EmbeddedRelated>
wrote:

>I work on a legacy code with a borland C++ compiler. The processor is an >Intel 80C186EB. Has an external Flash of 1MB - which has 256K of RAM. > >I am trying to dynamically allocate 64K(Size = 0x10000 = 65536 bytes) of >memory from RAM but looks like allocation is successful only for (0xFFFF = >65535 bytes). > >I tried to use a huge pointer - >>Byte __huge *pHugeDataBuffer = new (Byte __huge*)[65536L]; //returns NULL > >>Byte __huge *hptr1; >>Byte __huge *hptr2 = hptr1 + 65536; //successful > >I was only able to increment an address pointed by this huge pointer. >Could someone point me in the right direction?
It's been a long time, but IIRC Borland C(++) had hmalloc() [maybe with leading underscore] which could allocate chunks equal/larger than 64K. malloc/free can be used in C++ if you are careful: e.g., a C++ object located in a malloc'd block must be created using placement new() and destroyed *manually* by calling its destructor (~) function ... do NOT call delete() on such objects or you'll completely f_ up your heap. If applicable, the malloc'd block itself should be free()'d when you're done with it. Again, do not use delete(). You need to keep a huge pointer to the base address of your block, and if you subdivide it, use huge pointers and huge arithmetic when creating new pointers into the block. You can convert them to far pointers to hand out to other code if the subdivisions themselves are smaller than 64K. The really important points are to use placement new() and _not_ to use delete(). Hope this helps, George
>On Wed, 22 Jun 2016 18:22:28 -0500, "srao" <109468@EmbeddedRelated> >wrote: > >>I work on a legacy code with a borland C++ compiler. The processor is
an
>>Intel 80C186EB. Has an external Flash of 1MB - which has 256K of RAM. >> >>I am trying to dynamically allocate 64K(Size = 0x10000 = 65536 bytes)
of
>>memory from RAM but looks like allocation is successful only for (0xFFFF >65535 bytes). >> >>I tried to use a huge pointer - >>>Byte __huge *pHugeDataBuffer = new (Byte __huge*)[65536L]; //returns
NULL
>> >>>Byte __huge *hptr1; >>>Byte __huge *hptr2 = hptr1 + 65536; //successful >> >>I was only able to increment an address pointed by this huge pointer. >>Could someone point me in the right direction? > >It's been a long time, but IIRC Borland C(++) had hmalloc() [maybe >with leading underscore] which could allocate chunks equal/larger than >64K. > >malloc/free can be used in C++ if you are careful: e.g., a C++ object >located in a malloc'd block must be created using placement new() and >destroyed *manually* by calling its destructor (~) function ... do NOT >call delete() on such objects or you'll completely f_ up your heap. > >If applicable, the malloc'd block itself should be free()'d when >you're done with it. Again, do not use delete(). > >You need to keep a huge pointer to the base address of your block, and >if you subdivide it, use huge pointers and huge arithmetic when >creating new pointers into the block. You can convert them to far >pointers to hand out to other code if the subdivisions themselves are >smaller than 64K. > >The really important points are to use placement new() and _not_ to >use delete(). > >Hope this helps, >George
Thanks George, but What do you mean when you say placement new()? --------------------------------------- Posted through http://www.EmbeddedRelated.com
On Thu, 23 Jun 2016 11:58:30 -0500, "srao" <109468@EmbeddedRelated>
wrote:

>What do you mean when you say placement new()?
Normally when you call new(), it allocates a memory block from the heap and then constructs the desired object (or array of objects) in that block. Placement new() is a variant that *only* constructs the desired object in an already existing memory block whose address is passed to the new() call. https://isocpp.org/wiki/faq/dtors#placement-new https://isocpp.org/wiki/faq/dtors#placement-delete https://isocpp.org/wiki/faq/dtors#calling-member-dtors https://isocpp.org/wiki/faq/dtors#memory-pools These links are (mostly) consecutive on the same page - start with the 1st one and just keep reading. I provided them all for completeness. One problem with placement new() is that there is no array version. To create an placed array, you need to determine the size of the elements and step a pointer performing a placement new() at the desired address of each element individually. Then to destroy the placed array, you must step through again calling the destructor of each element individually. [This implies that every element type must have both constructor and destructor - even if they are trivially empty.] This is actually what new[] does after allocating a heap block, and what delete[] does before releasing the block ... but you must do it all manually to (re)use an already existing block instead of allocating a new one. Hope this helps, George
>On Wed, 22 Jun 2016 18:22:28 -0500, srao wrote: > >> I work on a legacy code with a borland C++ compiler. The processor is
an
>> Intel 80C186EB. Has an external Flash of 1MB - which has 256K of RAM. >> >> I am trying to dynamically allocate 64K(Size = 0x10000 = 65536 bytes)
of
>> memory from RAM but looks like allocation is successful only for
(0xFFFF
>> > 65535 bytes). >> >> I tried to use a huge pointer - >>>Byte __huge *pHugeDataBuffer = new (Byte __huge*)[65536L]; //returns >>>NULL >>>Byte __huge *hptr1; >>>Byte __huge *hptr2 = hptr1 + 65536; //successful >> >> I was only able to increment an address pointed by this huge pointer. >> Could someone point me in the right direction? >> --------------------------------------- >> Posted through http://www.EmbeddedRelated.com >I will put aside the reason _why_ you want to allocate memory in an >embedded system -- usually this is a Bad Idea, so expect someone (maybe >me, if I get time) to question you closely on what you're trying to do, >and why.
>I'm pretty sure that the memory allocation only works up to 65536. This
>is consistent with the limitations of Borland under DOS (and, perhaps, of
>DOS itself). Remember that the 80186 is pretty much a 16-bit processor >with a strange memory paging scheme. So it's really easy to write a >memory allocator that only works on blocks up to 2^16. > >I suspect that you're going to have to make your own memory allocator. >You could test this by dredging through the header files ("new.h" is, I >think, the one you want to look for) and see what the argument is to the
>default new [] operator. I suspect that it'll be of type int, which >means that 65536 turns to zero. You can do the same thing for malloc --
>if it takes a 16-bit integer, then the memory system simply cannot >allocate more. > >Assuming that there isn't a "huge_malloc" (or something) already, you'll
>probably have to make one -- and you'll have to make a "malloc" and a >"free" to go along with it. Then, to add insult to injury, if my >suspicions are correct you won't be able to use new [] _at all_, and >will, instead, have to do it the old fashioned way. > >On the plus side, there's plenty of nice memory allocators out there, so
>you don't have to be on your own. > >-- > >Tim Wescott >Wescott Design Services >http://www.wescottdesign.com > >I'm looking for work -- see my website!
Thanks Tim --------------------------------------- Posted through http://www.EmbeddedRelated.com
The 2026 Embedded Online Conference