T.R | Title | User | Personal Name | Date | Lines |
---|
3042.1 | | WJG::GUINEAU | | Tue Oct 24 1989 18:27 | 6 |
| I just looked up free() in the ANSI version of K&R and it says
free is of return type void. So it doesn't return anything.
Not sure about Lattice free()...
John
|
3042.2 | Some more suggestions | BANKS1::MIANO | I see the N end of a S bound horse | Tue Oct 24 1989 20:12 | 36 |
| If would add something like:
enum block_type { Vnode=3482 } ;
and modify your structure
>typedef struct vnode {
> double Element[4];
> struct vnode *next;
enum block_type block_type ;
>} VertexNode;
>
>.
>.
>.
>VertexNode *VPtr;
>
And add
>Vptr = (VertexNode *)malloc(sizeof(VertexNode));
Vptr->block_type = Vnode ;
When you walk through the structure, after every
a = a-> next.
add
if ( a->block_type != Vnode ) { REPORT AN ERROR } ;
ALSO NOTE THAT
free(0) in the Lattice library Royally F*&Ks up your system.
How about creating routines allocate_vnode and deallocate_vnode
that allocate and free nodes. That way you can add debugging code for
memory allocation/freeing in one place.
John
|
3042.3 | Suggest you use AllocMem & FreeMem | DECSIM::GILLETT | What does soft wear? DTN 225-7172 | Tue Oct 24 1989 23:48 | 20 |
| Re: .0
Your original version looks fine to me, free() should set that memory
free, sort of. There is an issue of free block collection & compaction
(the C standard library memory management routines: malloc, calloc, and
free use managed space), but your nodes don't seem to be of varying
size, so this shouldn't be a problem.
Try this, until someone can verify that free() might be broken:
User the Amiga system service calls from Exec: AllocMem & FreeMem.
These are documented in both Exec and in Appendix A of your orange ROM
kernel manual. I'd look 'em both up for you, but my Amiga and
attendant docs are in a truck somewhere between Detroit &
Mass. (i'm relocating).
Lots 'O Luck,
chris
|
3042.4 | cast | MILKWY::JANZEN | cf. ANT::CIRCUITS,ANT::UWAVES | Wed Oct 25 1989 10:11 | 3 |
| aren't you supposed to just cast the result into unsigned long int or
somethign?
Tom
|
3042.5 | More info (correction) | MSBIS1::LANDINGHAM | Guy M.,BXB1-1/F11,293-5297 | Wed Oct 25 1989 11:36 | 25 |
| re: .4
Well, I've tried this two ways so far:
free(VPtr);
...causes free memory reported in WB title bar to slowly shrink
down to almost 0 then GURU.
free((VertexNode *)VPtr);
...again causes free memory to shrink, but more slowly than the
first example. This time the reported free memory gets down to
about 33K (from 600+ K), and the program terminates successfully.
(sorry, I mixed these two cases up in the first note.)
I don't understand this: for the dataset I'm testing with, I don't
allocate more than 144 nodes between free() sweeps. Shouldn't I see
free memory shrink to no less than 144 * sizeof(VertexNode) (roughly)?
Appreciate all the suggestions and help...
|
3042.6 | Not the cast | TLE::RMEYERS | Randy Meyers | Wed Oct 25 1989 18:40 | 45 |
| Re: .5
The argument to free(), for a remotely ANSI conforming compiler, is void *.
Void * is a pointer type that is compatible with any other pointer type.
It exists so that the argument of free need not be cast to anything
(and the result of malloc need not be cast).
Pre-ANSI compilers defined free as taking a char * argument. Tasteful
programmers would cast the argument of free to char * in the call.
In (one version of) your program, you have the following:
free((VertexNode *)VPtr);
This the cast is not needed. First, free does not take a VertexNode *
argument. Second, VPtr is (supposedly) already declared to be a
VertexNode *, and casting a value to its present type is never
needed.
I recommend that you remove the cast. It'll show that yer a cool dude.
The cast isn't your problem, anyway. On a 680x0, all pointers have
the same representation, and free doesn't really care what the type
the pointer is.
I suspect that the error in your program exists elsewhere. You
might have a pointer that goes wild and smashes the next field
of the structure or smashes internal memory management headers that
malloc and free put on the start of your node. You might have
bad or uninitialized next values in your nodes. You might be
calling free on 0 (not terminating your loop properly). You
might be accessing a node after you free it.
Make sure you don't have a loop like this:
while (vptr != NULL) {
free(vptr);
vptr = vptr->next; /* Very bad error here */
}
because after you free a piece of memory, you aren't allowed
to look at it again. And on the Amiga, there is a great danger
that someone may grab the memory you just deallocated and use
it for something else.
|
3042.7 | I'll look again, thanks | MSBIS1::LANDINGHAM | Guy M.,BXB1-1/F11,293-5297 | Wed Oct 25 1989 20:54 | 21 |
| re: .6
Thanks, Randy. Yup, I'll admit the first cast was a pitiful shot
in the dark. I was wondering how free() knew how many bytes to
return to the free list, and I can see from your reply that malloc
and free are tacking on some more info onto my chunk of memory.
I was fairly careful in writing the free-up sweep and used two pointers
to avoid the error you mention in your example loop. If I use
CodePRobe, I can keep track of the addresses of each mallocated
node and, stepping through the free-up sweep code, it appears that
everything is pointing in the right place when I call free(). I
will try the (char *) cast and check the code yet again.
I'm using Lattice 5.02 and it's interesting that the manual states
that their level 3 memory allocation functions are "fully compatible
with the ANSI standard" and yet they state that free() expects a
pointer to a character. Guess you can't believe everything you
read in a manual...
Thanks again.
|
3042.8 | Argument to free | TLE::RMEYERS | Randy Meyers | Wed Oct 25 1989 21:28 | 12 |
| Re: .7
>[Lattice states] their level 3 memory allocation functions are "fully
>compatible with the ANSI standard" and yet they state that free() expects
>a pointer to a character.
I suspect a documentation error (I thought they had this right). Type
out stdlib.h to see what type the argument really is.
>Guess you can't believe everything you read in a manual...
Guess that's true!
|
3042.9 | Casting, free(), & offer to help | DECSIM::GILLETT | What does soft wear? DTN 225-7172 | Wed Oct 25 1989 23:32 | 32 |
| re: .6
"...it'll show yer a cool dude..."
Cool dudes always, always, ALWAYS cast everything when the target does
not agree with the source type. The only way to guarentee portability
across platforms is to do type casting correctly (along with a bunch 'o
other stuff besides). Note that on most Digital projects, C code that
does not cast correctly will not make it through code review.
Re: Original topic
Got myself to an Amiga and ran a few simple tests. free() works "as
you'd expect it to" meaning that I got back that which I released,
regardless casting (or lack thereof). So, it looks like somthing else
is broke in your code. Probably .6 is correct...you're probably
walking all over something else.
If you're absolutely certain that your code is correct (if it's not
Amiga specific, maybe you should try running it on a different machine
just for grins), then it's time to examine your environment. Specific
interests would include your launch code, stack size, and the state of
the memory system prior to launch.
If you're truly ready to scream, email it to me, and I'll read it on my
lunch hour. I've done a lot on the Amiga (used to work for an Amiga
software house), and maybe I can spot something.
Later,
chris
|
3042.10 | About the argument to free() | TLE::RMEYERS | Randy Meyers | Fri Oct 27 1989 01:16 | 70 |
| Re: .9
> Cool dudes always, always, ALWAYS cast everything when the target does
> not agree with the source type. The only way to guarentee portability
> across platforms is to do type casting correctly (along with a bunch 'o
> other stuff besides).
Its very good advice to avoid representational dependencies, but it does
not quite fit the situation here.
To insure compatibility and transportability, the programmer must #include
proper declarations of all functions called. Once that is done, the
programmer should insert needed casts.
But, once the prototype of free() is included, free() takes any pointer
type as an argument. No cast is necessary.
If you desire to port the code to a non-ANSI C system, there are two
cases: the system uses a uniform representation for all pointers, or the
system uses different pointer representations for pointers to different
data types.
If the system uses a uniform pointer representation, then you don't
need the cast for the program to work. The modern code works for
the wrong reason. Over time, non-ANSI C systems are going to become
ANSI C. Then the modern code will still work, but for the right
reason.
If the system uses different representations for different types of
pointers, then there is a problem. The programmer would be forced to
insert the cast. Of course, if the programmer can hold off porting
his code until the system gets an ANSI C compiler, he or she can
avoid making the change. :-)
Systems without ANSI C compilers and that have non-uniform pointers
are rare, and getting rarer. DEC now writes code for bunches of
systems: clones, Macs, MIPS machines, etc. I don't know of any
of those platforms that have the double problem of no ANSI C and
non-uniform pointers.
It comes down to a judgment call:
1. Cast the argument of free() to char *. Works with everything.
Rarely needed. Weird from the future point of view. You cast
the argument to a type that isn't really the type of parameter
so the program will work on rare machines.
2. Don't cast the argument of free(). Works with everything except
pre-ANSI C compilers running on machines that do not have uniform
pointers. The code will never cause anyone to scratch their
head.
3. Define a typedef for the right type of the parameter of free on
your system and cast the argument to free to that type. It
works everywhere, but has the potential to really screw the
readability of the code.
4. Do #3, sort of: Go ahead and cast the argument of free to void *,
and take the strategy of typedef'ing void on the non-ANSI C compiler.
This only get you in trouble when you are working with a compiler
that has partially added support for void (I've seen such a compiler:
it supported void as a return type but did not allow pointer to
void).
My personal preference: #2, #4, #1, and as a distant last, #3.
Making calls to free() portable to systems with non-uniform pointers
and without ANSI C is a problem with small payback. The effort would
be much better spent removing dependencies on the sizes of types,
byte ordering, sign-ness preserving, and what have you.
|
3042.11 | Could be the stack | TLE::RMEYERS | Randy Meyers | Fri Oct 27 1989 01:23 | 9 |
| Re: .9
>... examine your environment. Specific interests would include your
>launch code, stack size, and the state of the memory system prior to
>launch.
Try using a huge stack. I've noticed that Lattice C programs running
under the debugger require large stacks. Weird stuff happens when
the stack overflows.
|
3042.12 | | BANKS1::MIANO | I see the N end of a S bound horse | Fri Oct 27 1989 12:08 | 12 |
| RE: < Note 3042.11 by TLE::RMEYERS "Randy Meyers" >
>Try using a huge stack. I've noticed that Lattice C programs running
>under the debugger require large stacks. Weird stuff happens when
>the stack overflows.
This is absolutely correct. A bug in the debugger makes
THREE-FOURTHS of the stack unusable so you need to make the
stack FOUR times larger than you would need if you were not
using the debugger.
John
|
3042.13 | Or use current software... | FRAMBO::BALZER | Christian Balzer DTN:785-1029 | Fri Oct 27 1989 12:34 | 7 |
| Re: .12
Or just use the 5.04 version of CodeProbe, which fixes that problem...
Regards,
<CB>
|
3042.14 | ...what cool dudes do... | DECSIM::GILLETT | What does soft wear? DTN 225-7172 | Sun Oct 29 1989 15:48 | 13 |
| re: .10
Gues I've been told :-) ! Your points are well taken when looking at C
from the ANSI point of view. Our group is developing for VAX and
MIPSco platforms, and we've found a lot of stuff in the MIPSco C
compiler that hardly qualifies as ANSI (well, same goes for VAX C,
except that VAX C is much more mature than MIPSco C).
Anyways, the problem here doesn't have anything to do with casting, so
this thread is getting worn.
chris
|
3042.15 | don't use free() | AIAG::WISNER | you may ask yourself 'How do I work this?'. | Tue Nov 07 1989 12:30 | 26 |
|
Here are some alternate approaches to memory allocation that you may
find useful.
I suggest that .0 should not use free(). Are you malloc'ing and
free'ing mostly VertexNode's? If so, then I suggest a different
approach. Instead of free'ing VertexNodes, push them onto a
"SpareVertexNodes" list. Write a GetVertexNode function which first
tries to pop a node off the spare's list; if no spare's exist, then
allocate a new node.
Also, you can save storage by guessing the average number of nodes that
your program will use, allocate one big block
size=(sizeof(node)*number) of nodes and
push all the nodes onto the spare's list. This way, each node does not
have the header that malloc and free would create for each node.
If you use the intuition AllocRemember() function, then you can easily
free all the memory you allocated when you exist your program using the
FreeRemember() function; these two functions automatically maintain a
list of all your allocations.
|
3042.16 | memory management tips | TLE::RMEYERS | Randy Meyers | Tue Nov 07 1989 14:01 | 19 |
| RE: .15
> If you use the intuition AllocRemember() function, then you can easily
> free all the memory you allocated when you exist your program using the
> FreeRemember() function; these two functions automatically maintain a
> list of all your allocations.
If you use the C library memory management routines (malloc/calloc/free)
then memory will be freed when you program exits by calling exit(), abort(),
or returning from the main().
Note that it doesn't return the memory if you call the AmigaDOS routine
Exit(), but then Exit() is evil for a number of reasons (Workbench
programs are never unloaded if they call Exit()!).
The advice in .15 about maintaining your own free list and doing
zoned memory management is good, and will improve your performance.
I don't think it will fix the bug that is in your program, although
it may make it go into hiding by shifting the memory map around.
|