[comp.os.msdos.programmer] Memory Models in TC2.0

schikore@mentor.cc.purdue.edu (Dan Schikore) (02/19/91)

A program that I am writing uses dynamic structures of size ~12K, and will
not allow me to allocate memory for more than 3 structures.  I am trying
to compile using a different memory model and having some difficulty.  What
must be done to use a different memory model?  I tried first using the -mc
option on the tcc command line, and I have had all sorts of problems with
the program doing unexpected things.  When you change memory models do you
have to specify the change in pointer types?  (I also tried this changing
all pointers to far pointers and malloc to farmalloc, etc).  Basically, are
there some pitfalls that I have to look out for in changing the default
memory model?  Any help would be appreciated.

Thanks,

-Dan Schikore
schikore@mentor.cc.purdue.edu

Ralf.Brown@B.GP.CS.CMU.EDU (02/20/91)

In article <6246@mentor.cc.purdue.edu>, schikore@mentor.cc.purdue.edu (Dan Schikore) wrote:
}to compile using a different memory model and having some difficulty.  What
}must be done to use a different memory model?  I tried first using the -mc
}option on the tcc command line, and I have had all sorts of problems with
}the program doing unexpected things.  When you change memory models do you
}have to specify the change in pointer types?  (I also tried this changing
}all pointers to far pointers and malloc to farmalloc, etc).  Basically, are
}there some pitfalls that I have to look out for in changing the default
}memory model?  Any help would be appreciated.

A major pitfall is the assumption that ints and pointers are the same
size.  You also need to make sure every function which returns a pointer
is properly declared/prototyped, or the segment portion of the pointer
will be lost.  Turn on ALL warnings (-w on TCC) and fix all of the
warnings (by adding header files, prototypes, explicit casts, etc)
before proceeding.

--
{backbone}!cs.cmu.edu!ralf  ARPA: RALF@CS.CMU.EDU   FIDO: Ralf Brown 1:129/3.1
BITnet: RALF%CS.CMU.EDU@CMUCCVMA   AT&Tnet: (412)268-3053 (school)   FAX: ask
DISCLAIMER?  Did  | It isn't what we don't know that gives us trouble, it's
I claim something?| what we know that ain't so.  --Will Rogers

x041sc@tamuts.tamu.edu (Sean Malloy) (06/04/91)

I'm sure that this is a question that should be included in a FAQ
for this group, but I couldn't find a general FAQ in the message 
list.
 
I'm writing a (rather large) application in Turbo C 2.0 and I've
come to the point where I need to use either the Compact or Large
memory models instead of the small.  I've gone through my code and 
changed all the pointers and functions that deal with data that is
malloc()'d to be far (ie OBJECT far *draw_haxis(OBJECT far *BOX) { )
and the compiler seems to be quite happy.  No warnings; no errors.
 
(I realize that my life would be much easier using an OOL, but
my company won't buy C++ right now... ;-(.
 
The following fragment works under the small memory model, but not
under the Compact, Large, or Huge models, and I'm going nuts trying
to figure out why.  Any suggestions?
 
------------------- Begin Fragment --------------------
 
 
OBJECT far *new_object(enum obtype type) {
    OBJECT *ptr;
    coor d;
 
    d.x = 0;                 d.y = 0;
    if ((ptr = ((OBJECT far *)malloc(sizeof(OBJECT)))) == NULL ) {
       perror("New_object failed to allocate memory.  ABEND");
       exit(0);
    }
    if (obhead == NULL) { obhead = ptr;  endob =  ptr; }
    else { endob->next = ptr;    ptr->prev = endob;      endob = ptr; }
    ptr->type                    = type;
    ptr->parent                  = NULL;
    ptr->child                   = NULL;
    ptr->next                    = NULL;
 
-----------------End Fragment---------------------------------
 
...where of course OBJECT is a struct (with pointers to other 
structs, unions, etc  -- a data structure from hell)
 
My problem is that the assignment "ptr->type = type;" fails to 
change the value of ptr->type, even though malloc seems to work 
correctly  (According the integrated debugger
inside Turbo C) and my program fails because of this little
inconvience.  Do I have to declare my structs as far data items?  
If so, can someone provide me with an example - I can't seem to find
one in any of my references...
 
Thanks
 
-Sean
.

mattel@auto-trol.com (Matt Telles) (06/05/91)

In article <16856@helios.TAMU.EDU> x041sc@tamuts.tamu.edu (Sean Malloy) writes:
>I'm sure that this is a question that should be included in a FAQ
>for this group, but I couldn't find a general FAQ in the message 
>list.
> 
>    if ((ptr = ((OBJECT far *)malloc(sizeof(OBJECT)))) == NULL ) {
>       perror("New_object failed to allocate memory.  ABEND");
>       exit(0);
   Now, this would just be a guess, but I would say that you do not include the
header file for malloc.  This tells the compiler that the function returns an
int, which it will happily convert to a pointer in small model.  In large model,
other weird things will happen.
   I could be completely wrong, in which case you can just ignore this...

Matt
the net.lurker

-- 
==============================================================================
Matt Telles 	                 mattel@auto-trol.COM
                                 {...}ncar!ico!auto-trol!mattel
Auto-trol Technology 12500 N Washington Denver, CO 80241-2404 (303)252-2874

kevino@pollux.svale.hp.com (Kevin Owen) (06/05/91)

Sean,

I went through this same problem and found that the secret was to change 
all calls to "malloc()" to "farmalloc()".  It appears that compiling in
the compact and large models automagically sets all of your data types to
"far" but does not change the values that functions return.

Good Luck.
_______________________________________________________________________________

 _   ,                   __                 Kevin Owen @ Hewlett-Packard
' ) /                   / ')                Sunnyvale, California
 /-<   _ , __o  ____   /  / , , , _  ____   Phone :    (408) 720-3845
/   ) </_\/ <__/ / <  (__/ (_(_/_</_/ / <_  UN*X Mail  ...hplabs!hpcc01!kevino
_______________________________________________________________________________

alexande@borland.com (Mark Alexander) (06/06/91)

In article <4660001@pollux.svale.hp.com> kevino@pollux.svale.hp.com (Kevin Owen) writes:
>I went through this same problem and found that the secret was to change 
>all calls to "malloc()" to "farmalloc()".  It appears that compiling in
>the compact and large models automagically sets all of your data types to
>"far" but does not change the values that functions return.

There are couple of mistakes here.

1. You should not have to use farmalloc() instead of malloc() --
farmalloc() is identical to malloc() in large data models.  Nor should
you have change all your pointer variables to far (as an earlier
posting suggested).

2. Pointer variables, pointers returned by functions, and pointers
passed to functions will automatically become far pointers in large
data models, unless you explicitly make them near.

Perhaps the problem was that the program did not include <stdlib.h> or
otherwise include a prototype for malloc().  Or perhaps the wrong
run-time library was being linked.

grimlok@hubcap.clemson.edu (Mike Percy) (06/07/91)

alexande@borland.com (Mark Alexander) writes:

>In article <4660001@pollux.svale.hp.com> kevino@pollux.svale.hp.com (Kevin Owen) writes:
>>I went through this same problem and found that the secret was to change 
>>all calls to "malloc()" to "farmalloc()".  It appears that compiling in
>>the compact and large models automagically sets all of your data types to
>>"far" but does not change the values that functions return.

>There are couple of mistakes here.

>1. You should not have to use farmalloc() instead of malloc() --
>farmalloc() is identical to malloc() in large data models.  Nor should
>you have change all your pointer variables to far (as an earlier
>posting suggested).
 
Sorry.  In large data memory models, malloc() is still not identical to
farmalloc().  
  To wit, the prototypes (less _cdecl and the like) are
    void * malloc(size_t size);
    void far *farmalloc(unsigned long size);

In large data memory models, both do return far pointers, since malloc
has no specifier, it default to near in small data models and far in
large data models.  But malloc still can only allocate < 64K of data.
It's try that both are taking memory from the far heap -- in fact, after
casting from size_t to unsigned long, malloc calls farmalloc (in large
data meory models).  But they are _not_ identical.
 
And unless you really know what's going to be what, don't mess around
with declaring functions or data pointers far or near. Doing this and
then changing memory models is a sure way to break code. 

>2. Pointer variables, pointers returned by functions, and pointers
>passed to functions will automatically become far pointers in large
>data models, unless you explicitly make them near.

As I said before, it's not really a good idea to explicitly define
pointers as far/near unless you absolutely must (and know what you're
doing).  Leaving modifiers off is safe, provided all modules are
compiled under the same memory model.

>Perhaps the problem was that the program did not include <stdlib.h> or
>otherwise include a prototype for malloc().  Or perhaps the wrong
>run-time library was being linked.
 
far*alloc functions are defined in <alloc.h>
    

iisakkil@vipunen.hut.fi (Mika R Iisakkila) (06/07/91)

grimlok@hubcap.clemson.edu (Mike Percy) writes:

> Sorry.  In large data memory models, malloc() is still not identical to
> farmalloc().  

Guess what the Borland malloc (TC2.0) does in large data models?
"return farmalloc((unsigned long) nbytes)" (believe me, I have the
source). So your large data model programs would be a bit faster, if
you used farmalloc() instead of malloc(). But as you said, they are
not interchangable because the argument of malloc() is an int and the
argument of farmalloc() is long.

> As I said before, it's not really a good idea to explicitly define
> pointers as far/near unless you absolutely must (and know what you're
> doing).  Leaving modifiers off is safe, provided all modules are
> compiled under the same memory model.

Very true - and it is very important to include all the necessary
prototypes, as this example shows us.

alexande@borland.com (Mark Alexander) (06/07/91)

In article <1991Jun6.182748.27627@hubcap.clemson.edu> grimlok@hubcap.clemson.edu (Mike Percy) writes:
>alexande@borland.com (Mark Alexander) writes:

[Something hasty about malloc() being identical to farmalloc() in large data
models...]

>Sorry.  In large data memory models, malloc() is still not identical to
>farmalloc().  
>  To wit, the prototypes (less _cdecl and the like) are
>    void * malloc(size_t size);
>    void far *farmalloc(unsigned long size);

You're right - my mistake.  But other than that, the functions really
are the same.  Effectively, malloc() puts a zero in the high word of
the size and jumps to the common entry point for both functions.

I still don't understand what the problem was in the original posting,
though.  If someone has a simple test program that demonstrates a
problem with malloc(), I'd be happy to look at it.

x041sc@tamuts.tamu.edu (Sean Malloy) (06/12/91)

Well, sorry I didn't post this response eariler, but things have 
been rather hectic around here recently...  I'm the one who posted 
the original message about the problem with malloc().
 
I tried (on my own initative, thank you) nearly all of the 
suggestions that were posted/mailed to me. (most of them regarding 
a pointer type mismatch and/or the supposed non-declaration of
'malloc()').  In the larger models, farmalloc() seemed to work the 
same as malloc() [and this is consistant with my references] and 
the use of far is unnecessary, but what I posted was ~ the 20th
thing I'd tried.  Basically, I was thinking that the compiler was 
(for some reason) feeding me near pointers, and I was using brute 
force to make them all far.  Messy, yes.  Unnecessary, yes.
 
After some discussion with a tech-rep at Borland [BTW - is there
Internet tech-support from Borland?  The telephone tag I played 
that day for more than an hour before I got to talk to a real 
person was nearly enough to make me go out and buy a copy of 
Microsoft C, just for the support...] we determined that my machine 
was running out of memory, even though malloc wasn't returning a 
NULL pointer.  I turned on every warning (besides the ANSI stuff) 
that I could find, and made a few corrections...
 
It worked... (well, malloc returned NULL at the place where it used 
to just fail... ;-)  *sigh*  now can someone recommend a decent
extended memory manager... ;-) OR, does Borland have a product that
will allow me to write in 32-bit protected mode?  [I'd like to be 
able to easily address *all* my memory, thank you...]
 
We have a copy of Metaware High C collecting dust here that is a 32 
bit (protected mode) compiler, but no one around here has picked it 
up yet, and Borland's integrated debugger is a godsend from time to 
time...  I'm a bit reluctant to use a compiler from another 
vendor if I can avoid it...
 
Thanks for all the replies... after all that, it came down to a 
matter of the toy machine that I'm developing on...
 
-Sean

#include <std/disclaimer.h>