zupke@jato.Jpl.Nasa.Gov (Brian Zupke ) (01/07/90)
Howdy! I'm working on a C program that loads a font from disk using OpenDiskFont(), uses it with SetFont(), and then gets rid of it later with CloseFont(). My problem is that each time I run my program, I lose around 3k-4k bytes of memory (very close to the size of the font on disk). I've tried numerous combinations of font functions (even RemFont()) and still have this problem. Does anyone know if there's a bug in the font functions, or am I doing something wrong? Thanks in advance. --Brian
addison@pollux.usc.edu (Richard Addison) (01/08/90)
In article <2528@jato.Jpl.Nasa.Gov> zupke@jato.Jpl.Nasa.Gov (Brian Zupke (JPL Amiga Club Pres.)) writes: >Howdy! I'm working on a C program that loads a font from disk using >OpenDiskFont(), uses it with SetFont(), and then gets rid of it later with >CloseFont(). My problem is that each time I run my program, I lose around >3k-4k bytes of memory (very close to the size of the font on disk). I've >tried numerous combinations of font functions (even RemFont()) and still >have this problem. Does anyone know if there's a bug in the font functions, >or am I doing something wrong? > >Thanks in advance. > >--Brian Well, you don't need to worry about it. When the system gets low on memory, it will automagically free the memory that is used for the font. Now, if you _really_ want to get that memory back immediately, you can request an impossibly large amount of memory with AllocMem(). This will flush all unused resources from memory. (This is one of the main reasons that the documents keep telling you to close everything you open, so it can keep track). But again, I recommend that you avoid doing this. After all, if your program (on another one) needs this font again, it will save time if it doesn't have to reload it. BTW, try "loadwb -debug" sometime and look for the invisible menu to the right of 'special'. See 'flushlibs'? Don't try "Debug" unless you have a terminal connected to your serial port. Richard Addison
root@ccave.UUCP (Juergen Hermann) (01/09/90)
In article <2528@jato.Jpl.Nasa.Gov> zupke@jato.Jpl.Nasa.Gov (Brian Zupke ) writes: >Howdy! I'm working on a C program that loads a font from disk using >OpenDiskFont(), uses it with SetFont(), and then gets rid of it later with >CloseFont(). My problem is that each time I run my program, I lose around >3k-4k bytes of memory (very close to the size of the font on disk). I've You MUST use OpenFont() to look for resident fonts before ever calling OpenDiskFont(). If not, the font is made resident over and over again, in fact loosing memory for nothing. So do something like if ((WinFont = (struct TextFont *) OpenFont (&ta)) == NULL && (WinFont = (struct TextFont *) OpenDiskFont (&ta)) == NULL) { Abort ("Can't open font\n"); } -- // Juergen Hermann UUCP: ira.uka.de!smurf!ccave!root \X/ 75 Karlsruhe 1, FRG Fido: 2:241/2.1212@FidoNet
a464@mindlink.UUCP (Bruce Dawson) (01/15/90)
> root writes: > > Msg-ID: <145@ccave.UUCP> > Posted: 9 Jan 90 03:21:25 GMT > > Org. : Chameleon's Cave [JDCP 0.96] > Person: Juergen Hermann > > You MUST use OpenFont() to look for resident fonts before ever calling > OpenDiskFont(). If not, the font is made resident over and over again, in > fact loosing memory for nothing. > > So do something like > > if ((WinFont = (struct TextFont *) OpenFont (&ta)) == NULL && > (WinFont = (struct TextFont *) OpenDiskFont (&ta)) == NULL) { > Abort ("Can't open font\n"); > } > > -- > // Juergen Hermann UUCP: ira.uka.de!smurf!ccave!root > \X/ 75 Karlsruhe 1, FRG Fido: 2:241/2.1212@FidoNet Are you sure about having to call OpenFont() to avoid losing memory? I have never seen that documented, and when I tried it just now (opened the same font several times, closing it after each opening, checking for memory loss, using OpenDiskFont() only) and I had no memory loss, except (of course) on the first open. .Bruce Dawson.
bevis@EE.ECN.PURDUE.EDU (Jeff Bevis) (01/16/90)
In article <145@ccave.UUCP>, root@ccave.UUCP (Juergen Hermann) writes: > >So do something like > > if ((WinFont = (struct TextFont *) OpenFont (&ta)) == NULL && > (WinFont = (struct TextFont *) OpenDiskFont (&ta)) == NULL) { > Abort ("Can't open font\n"); > } Well, I wouldn't do that either, because you can't be sure what the compiler is going to do with your code. You've got two expressions hooked together with a logical 'and' -- now which one will the final code try first? The one on the right? Uh-oh. This is better: If((WinFont=(struct TextFont *)OpenFont(&ta))==NULL) { If((WinFont=(struct TextFont *)OpenFont(&ta))==NULL) Abort("Can't open font\n"); } That way, OpenFont() will always go first. +--------------------------------+--------------------------------------------+ | Jeff Bevis | "But I don't like spam!" | | bevis@en.ecn.purdue.edu | Give me Amiga or nothing at all. | +--------------------------------+--------------------------------------------+
a464@mindlink.UUCP (Bruce Dawson) (01/17/90)
Ignoring the fact that OpenFont() is NOT needed before a call to OpenDiskFont(), there is nothing wrong with the following code: if (!(winfont = (struct TextFont *)OpenFont(&ta)) && !(winfont = (struct TextFont *)OpenDiskFont(&ta))) blah blah it didn't work. C _guarantees_ that the first expression will be evaluated first. Furthermore, it guarantees that if the first expression fails, the second expression will not be executed at all. If you look at K&R, you will find some programs that _depend_ on this for proper execution. However, as has been pointed out, from an Amiga point of view that code is bunk, because the call to OpenFont() isn't necessary. .Bruce.
kodiak@amiga.UUCP (Robert R. Burns) (01/17/90)
In article <145@ccave.UUCP> root@ccave.UUCP (Juergen Hermann) writes: )You MUST use OpenFont() to look for resident fonts before ever calling )OpenDiskFont(). If not, the font is made resident over and over again, in )fact loosing memory for nothing. False. OpenFont() is not needed here. OpenDiskFont() will use the memory version if no better version exists on disk. For 1.3 & earlier, this means the disk is hit every time looking for that "better match". This disk hit may be what confused you. For 1.4, if the match in memory is already as good as it can get, the disk won't be hit. To prepare for that, ensure that the ta_Style and ta_Flags you set in the TextAttr are those from the AvailFonts result: not just the ta_Name and ta_YSize. - Kodiak -- Bob Burns, amiga!kodiak _ | /_ _|. _ | Commodore __ |_) _ |_ _ )' |<(_)(_)|(_\|< /\ | ||| _` /\ |_)(_\| )(_\ | | \ Software ___/..\|\/|||__|/..\___ Faith
louie@sayshell.umd.edu (Louis A. Mamakos) (01/17/90)
In article <9001161446.AA29551@en.ecn.purdue.edu> bevis@EE.ECN.PURDUE.EDU (Jeff Bevis) writes: >>So do something like >> >> if ((WinFont = (struct TextFont *) OpenFont (&ta)) == NULL && >> (WinFont = (struct TextFont *) OpenDiskFont (&ta)) == NULL) { >> Abort ("Can't open font\n"); > >Well, I wouldn't do that either, because you can't be sure what the compiler >is going to do with your code. You've got two expressions hooked together >with a logical 'and' -- now which one will the final code try first? The one >on the right? According to my K&R, first edition in Appendix A "C Reference Manual", section 7.11: 7.11 Logical AND operator {\it logical-and-expression: expression && expression} The && operator groups left-to-right. It returns 1 if boths its operands are non-zero, 0 otherwise. Unlink &, && guarantees left-to-right evaluation; moreover the second operand is not evaluated if the first operand is 0. So the example code posted works just fine. louie
mcafee@tallis.dec.com (Steve McAfee) (01/17/90)
In article <5125@amiga.UUCP>, kodiak@amiga.UUCP (Robert R. Burns) writes... >In article <145@ccave.UUCP> root@ccave.UUCP (Juergen Hermann) writes: >)You MUST use OpenFont() to look for resident fonts before ever calling > >False. OpenFont() is not needed here. > >OpenDiskFont() will use the memory version if no better version exists on disk. > Interesting because I've noticed a loss of about 4K bytes occaisonally and this prompted me to run Dave Haynie's SETFONT a couple of times. Sure enough every time I do a SETFONT SIESTA 14 WINDOW I lose about 4K and flushing doesn't help. Here's the code fragment from Dave's c++ version: TextFont *font() { TextFont *f = OpenDiskFont(&sfattr); if (!f) f = OpenFont(&sfattr); if (!f) fail("Font \"%s\" not found\n",sfattr.ta_Name); return f; } This also raises the question, if I SETFONT in a CLI window and then endcli that window, is that font permanently in memory or did someone decrement the appropriate counter somewhere? Apparently not because I did this a couple of times and flushing didn't get rid of them. xoper shows me a bunch of copies sitting out there. I don't have c++ or I would fix this. Are you out there Dave? - steve mcafee
gregg@cbnewsc.ATT.COM (gregg.g.wonderly) (01/18/90)
From article <9001161446.AA29551@en.ecn.purdue.edu>, by bevis@EE.ECN.PURDUE.EDU (Jeff Bevis): > Well, I wouldn't do that either, because you can't be sure what the compiler > is going to do with your code. You've got two expressions hooked together > with a logical 'and' -- now which one will the final code try first? The one > on the right? Uh-oh. This is better: C was designed by people who had more insight into reality than this. Logical expressions are guaranteed to evaluate from left to right so the original code is indeed correct. Your's is too, but changing it is not necessary to get the desired behavior. i.e. if ((b = call_func_b ()) == NULL || (a = call_func_a(b)) == NULL) { /* Do something, both didn't work. */ } will call "call_func_a" if the first condition (call_func_b returning NULL) is false, but will not call "call_func_a" if "call_func_b" returns NULL. This means that one can guarantee that the parameter to "call_func_a" will be the value returned from "call_func_b", and it will not be "NULL". One of the nicest things about C is that the behavior of the compiler is almost always defined for expression evaluation. Excepting the classic mistake of *p++ = *p & 0x7f; which, is not guarateed to evaluate the *p on the right before the *p++ on the left of the assignment operator. -- ----- gregg.g.wonderly@att.com (AT&T bell laboratories)
bevis@EE.ECN.PURDUE.EDU (Jeff Bevis) (01/19/90)
In article <1990Jan17.013417.20587@haven.umd.edu>, louie@sayshell.umd.edu (Louis A. Mamakos) writes: > >According to my K&R, first edition in Appendix A "C Reference Manual", >section 7.11: > > 7.11 Logical AND operator > > {\it logical-and-expression: > expression && expression} > > The && operator groups left-to-right. It returns 1 if boths its > operands are non-zero, 0 otherwise. Unlink &, && guarantees > left-to-right evaluation; moreover the second operand is not > evaluated if the first operand is 0. > >So the example code posted works just fine. > >louie [red, embarrassed face omitted] I have obviously been using memory-destructive drugs. Indeed I was wrong... and I apologize for spreading bogus myth.... I would rather change my previous statement to the form of "using two if's instead of the && would be clearer and less confusing" instead of what I did state. In some languages, the statement in question would present a problem of ambiguity, but thanks to K&R, not in C. At any rate, I am *never* going to loan out my K&R reference again, for if I hadn't, I would've looked this up first.... :-( +--------------------------------+--------------------------------------------+ | Jeff Bevis | "But I don't like spam!" | | bevis@en.ecn.purdue.edu | Give me Amiga or nothing at all. | +--------------------------------+--------------------------------------------+
doug@xdos.UUCP (Doug Merritt) (01/22/90)
In article <9001182253.AA18421@en.ecn.purdue.edu> bevis@EE.ECN.PURDUE.EDU (Jeff Bevis) writes: > >I have obviously been using memory-destructive drugs. Indeed I was wrong... >and I apologize for spreading bogus myth.... I would rather change my previous >statement to the form of "using two if's instead of the && would be clearer >and less confusing" instead of what I did state. I don't mean this to be a flame, but that's not true either. This construct is called "short circuit evaluation", and is as much a hallmark of C as are, say, increment operators like "++i". It is *not* considered unclear to take advantage of this feature. Quite the opposite. It's true that features of a language which are not universally used in other languages can be confusing to new users of that language. But that doesn't mean they should be avoided. One should, in general, write code that assumes general fluency on the part of the reader, rather than trying to write code which assumes that the reader is a novice in the language. Doing so would mean wholly avoiding such language features, implying that there is something wrong with using them. There is not. As a matter of fact, this is an area in which C has been rather influential. As with the "++" operator, the short circuit evaluation feature has been adopted more and more widely in new languages. This is simply to stress that it *is* a feature. As with any design, one should not confuse novice usability (learning curve issues) with expert usability. By analogy, the Amiga's multitasking features have been confusing to learn to work with for programmers accustomed to non-multitasking systems like the IBM PC and the C64, etc, but that doesn't make those features bad. They were not confusing to programmers who were already accustomed to multitasking environments, particularly those who were used to message passing as well. It's just a question of which metaphors one has previous familiarity with. Doug -- Doug Merritt {pyramid,apple}!xdos!doug Member, Crusaders for a Better Tomorrow Professional Wildeyed Visionary