Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #41500 > unrolled thread
| Started by | partremmaps@gmail.com |
|---|---|
| First post | 2014-03-08 22:08 -0800 |
| Last post | 2014-03-30 04:22 +0000 |
| Articles | 5 on this page of 45 — 14 participants |
Back to article view | Back to comp.lang.c
Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-08 22:08 -0800
Re: Does ANSI C allow free() to always be empty? Kaz Kylheku <kaz@kylheku.com> - 2014-03-09 06:55 +0000
Re: Does ANSI C allow free() to always be empty? David Brown <david.brown@hesbynett.no> - 2014-03-10 00:47 +0100
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-09 22:37 -0700
Re: Does ANSI C allow free() to always be empty? David Brown <david.brown@hesbynett.no> - 2014-03-10 10:20 +0100
Re: Does ANSI C allow free() to always be empty? Keith Thompson <kst-u@mib.org> - 2014-03-10 08:52 -0700
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-10 20:51 -0700
Re: Does ANSI C allow free() to always be empty? Robert Wessel <robertwessel2@yahoo.com> - 2014-03-11 01:08 -0500
Re: Does ANSI C allow free() to always be empty? David Brown <david.brown@hesbynett.no> - 2014-03-11 12:52 +0100
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-12 00:09 -0700
Re: Does ANSI C allow free() to always be empty? David Brown <david.brown@hesbynett.no> - 2014-03-12 12:59 +0100
Re: Does ANSI C allow free() to always be empty? Kaz Kylheku <kaz@kylheku.com> - 2014-03-10 09:01 +0000
Re: Does ANSI C allow free() to always be empty? Nick Bowler <nbowler@draconx.ca> - 2014-03-10 15:56 +0000
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-09 01:11 -0800
Re: Does ANSI C allow free() to always be empty? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-03-09 12:39 +0000
Re: Does ANSI C allow free() to always be empty? gazelle@shell.xmission.com (Kenny McCormack) - 2014-03-09 13:05 +0000
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-09 22:28 -0700
Re: Does ANSI C allow free() to always be empty? Martin Shobe <martin.shobe@yahoo.com> - 2014-03-10 07:27 -0500
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-10 20:55 -0700
Re: Does ANSI C allow free() to always be empty? Martin Shobe <martin.shobe@yahoo.com> - 2014-03-11 08:19 -0500
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-11 23:22 -0700
Re: Does ANSI C allow free() to always be empty? Martin Shobe <martin.shobe@yahoo.com> - 2014-03-12 08:09 -0500
Re: Does ANSI C allow free() to always be empty? James Kuyper <jameskuyper@verizon.net> - 2014-03-12 11:29 -0400
Re: Does ANSI C allow free() to always be empty? Martin Shobe <martin.shobe@yahoo.com> - 2014-03-10 07:29 -0500
Re: Does ANSI C allow free() to always be empty? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-09 09:14 +0000
Re: Does ANSI C allow free() to always be empty? Robert Wessel <robertwessel2@yahoo.com> - 2014-03-10 15:33 -0500
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-09 23:05 -0700
Re: Does ANSI C allow free() to always be empty? Martin Shobe <martin.shobe@yahoo.com> - 2014-03-10 07:43 -0500
Re: Does ANSI C allow free() to always be empty? gordonb.3qcze@burditt.org (Gordon Burditt) - 2014-03-10 12:05 -0500
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-10 20:16 -0700
Re: Does ANSI C allow free() to always be empty? Tim Rentsch <txr@alumni.caltech.edu> - 2014-03-29 16:27 -0700
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-10 21:48 -0700
Re: Does ANSI C allow free() to always be empty? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-11 05:52 +0000
Re: Does ANSI C allow free() to always be empty? partremmaps@gmail.com - 2014-03-20 19:14 -0700
Re: Does ANSI C allow free() to always be empty? Kaz Kylheku <kaz@kylheku.com> - 2014-03-21 03:25 +0000
Re: Does ANSI C allow free() to always be empty? Richard Damon <Richard@Damon-Family.org> - 2014-03-21 20:58 -0400
Re: Does ANSI C allow free() to always be empty? Tim Rentsch <txr@alumni.caltech.edu> - 2014-03-29 16:11 -0700
Re: Does ANSI C allow free() to always be empty? Richard Damon <Richard@Damon-Family.org> - 2014-03-29 22:27 -0400
Re: Does ANSI C allow free() to always be empty? Tim Rentsch <txr@alumni.caltech.edu> - 2014-03-30 13:18 -0700
Re: Does ANSI C allow free() to always be empty? Richard Damon <Richard@Damon-Family.org> - 2014-03-30 20:49 -0400
Re: Does ANSI C allow free() to always be empty? Tim Rentsch <txr@alumni.caltech.edu> - 2014-04-17 10:52 -0700
Re: Does ANSI C allow free() to always be empty? James Kuyper <jameskuyper@verizon.net> - 2014-03-31 11:18 -0400
Re: Does ANSI C allow free() to always be empty? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-21 03:31 +0000
Re: Does ANSI C allow free() to always be empty? Tim Rentsch <txr@alumni.caltech.edu> - 2014-03-29 15:39 -0700
Re: Does ANSI C allow free() to always be empty? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-30 04:22 +0000
Page 3 of 3 — ← Prev page 1 2 [3]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2014-04-17 10:52 -0700 |
| Message-ID | <kfnzjjjc07u.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #42370 |
Richard Damon <Richard@Damon-Family.org> writes: > On 3/30/14, 4:18 PM, Tim Rentsch wrote: >> Richard Damon <Richard@Damon-Family.org> writes: >> >>> On 3/29/14, 7:11 PM, Tim Rentsch wrote: >>>> Richard Damon <Richard@Damon-Family.org> writes: >>>>> My feeling is that based on this, if an vendor provided an >>>>> implementation that claimed to conform to the C standard, and >>>>> in the implementation free was always vacuous (and provided no >>>>> other way in background to recover the memory), it would >>>>> probably be found guilty of false advertising as the standard >>>>> does say that free will make the memory available for future >>>>> allocations. >>>> >>>> An attorney arguing that point of view would have a significant >>>> uphill battle. Section 5.1.2.3 p6 spells out pretty clearly what >>>> the bar is for being a conforming implementation, and it depends >>>> only on externally observable behavior, not on any implementation >>>> internal details. Moreover if any member of the WG14 committee >>>> were called to offer expert testimony in the case, I'm confident >>>> their testimony would be that such questions are concerned only >>>> with quality of implementation, and so are deliberately outside >>>> of what the Standard considers in defining conformance. >>> >>> Actually, since that clause specifies that the output be correct >>> according to what the abstract semantics would have produced, and >>> the definition of free is to make the memory available for further >>> allocations, this clause can NOT be used to excuse a reasonable >>> reading to require free to at least attempt something. >> >> The key point is that whether an implementation is conforming >> depends only on its behavior. If we have two implementations >> that exhibit the same behavior, then if one is conforming the >> other is also, regardless of how they are coded. It's easy to >> sketch out an implementation that obviously does try to conform >> to the spirit of the free()/malloc() descriptions, and be >> conforming otherwise, yet would exhibit the same behavior as an >> implementation with an empty free() body. Because conformance is >> determined solely by behavior, we can't say one is conforming and >> the other isn't - either both are or neither is. Do you mean to >> say that the Standard requires malloc() must succeed under some >> circumstances? If so then which portions of the Standard provide >> such requirement? If not then the "sincere" implementation is >> conforming and so must also the "insincere" implementation be. > > First, this statement is false, because an important part of the > equation that needs to be considered is the documentation for the > implementation, it is quite possible for two implementation to > behave identically and one to conform and one to not, because one > might document implementation differently. I didn't mention this because I thought it was obvious. Of course what I'm talking about is implementations that share the same values for implementation-defined parameters, etc. We might call such implementations "simpatico". > The definition of /observable behavior/ refers back to the > abstract machine, and says, in essence, that observable outputs > must match that of the abstract machine, so it is allowed to do > things differently in the real machine than the abstract machine, > as long as we can't "see" the difference on the outside. > > Note that the memory allocation function, are defined at the > abstract machine level to allocated memory or null if it CANNOT > be allocated. This would imply that the implementation needs to > actually attempt to return the requested block, so an > implementation that returns a null when it could return a request > block has failed to meet a requirement of the standard. It > doesn't matter if the program can detect that it could have. This conclusion is not consistent with 5.1.2.3 p6 (or p5 in n1256), which starts "The least requirements on a conforming implementation are: ...". > Another problem with looking at behavior (at least as a black > box) is that it is impossible to prove conformance. A conforming > implementation has required behavior on every possible conforming > program, with every possible input. As this is an infinite job, > it will take an infinite time. Also, some parts of observable > behavior might not be really observable in practice. For > instance, the standard requires that ALL volatile objects be > accessed in accordance to the virtual machine, including those in > "normal" memory. On many machines, this is impossible to do. > Also, some behavior is allowed in the case of "failure", and > (unless you want to allow to arbitrary fail on any or every > case), it is often impossible for the program to determine that > something really failed, and it could be claimed that for an > implementation to call something a failure, when there really > wasn't a failure, is a deviation from the abstract machine, and > thus a non-conformity. > > This says that conformance determination MUST be "White Box", > where we can look at how it does things, so we can abstractly > determine what will happen in the infinitely large case. This > says that we CAN know internal details about if a failure really > did happen or not,and thus insincerity (declaring a failure when > there wasn't) is possible. You have the burden of proof here backwards. The person making a claim of false advertising has to prove the implementation is not conforming, not the other way around. The only way to do this is to supply a program whose output could _not_ have been produced by a conforming "simpatico" implementation. This is quite a high bar. Furthermore, since it is easy to demonstrate an alternative simpatico implementation that clearly is conforming and has the same behavior, there is an affirmative defense to any such program offered. >>> As to being merely quality of implementations, most jurisdictions >>> have laws that require products to have at least certain very >>> minimal levels of quality to be offered. >> >> I won't disagree, but that doesn't have anything to do with >> the question of false advertising as regards being a conforming >> implementation. >> >>> After all, would YOU allow someone to say the following is a C >>> compiler: a shell script that checked if a file matches a >>> specific sample, if it matches copy another file to a specified >>> place, and if not print a message? >>> >>> By a strict reading of the standard, such a script (with >>> appropriate documentation) seems to meet all that the standard >>> requires. After all, 5.2.4.1 only requires the ability to execute >>> "at least one program ...", and may (because there is no other >>> requirement) indicate that any other program for any reason >>> doesn't meet the translation limits. There is a footnote >>> (non-normative) to avoid fixed limits whenever possible, but that >>> is 1) not normative, and 2) doesn't actually require anything. >> >> Your analysis is incomplete. There are two other significant >> requirements of a conforming implementation, namely, it must >> "accept" any strictly conforming program, and it must "reject" any >> program with a (non-skipped) #error directive. These additional >> requirements actually raise the bar quite a bit, and it isn't >> nearly so easy to provide a conforming implementation as the >> script outlined above. However let me ignore those details and >> respond to your question as if that didn't matter. > > The problem with that distinction is that then I suspect that NO > implementation is conforming, as, if you can't stop based on > implementation limits, it is possible to create an arbitrary > large program that must be parsed to determine if a #error is > skipped or not. This conflates two different items, namely, an implementation and the data processing system on which the implementation might be run. There is no requirement, for example, that an implementation must be runnable on a system with 512 bytes of RAM, or any fixed amount of RAM. What is required of an implementation is only that it would behave appropriately if run on a system with sufficient resources available. Such concerns are explictly outside the scope of the Standard (section 1 paragraph 2). > Since we MUST allow an implementation to declare a translation > limit before the accept/reject decision (or our set of conforming > implementations is empty), the script passes just as well as > Clang or GCC (maybe even better,as it is much less likely to have > a bug causing it to make the wrong determination, or accept and > then miss-translate a program). Again a distinction needs to be made between an implementation and the data processing system on which the implementation might be run. Limitations that arise as a consequence of lack of resources in the data processing system are not translation limits but just limitations in the surrounding environment. For example, an implementation won't be able to compile a program if there is zero disk space available, but that's not a translation limit. >> If someone provided such an (extremely limited) implementation, and >> claimed it was a conforming implementation, which is the question >> under discussion, I would /agree/ that it is conforming. The >> reason I would agree is that I believe this is what the authors >> of the Standard intented. This point is discussed at some length >> in the Rationale document. The authors are fully aware that such >> contrivances are possible, yet still chose to define conformance >> as they did, knowing full well that the definition adopted allows >> such subterfuges. I believe it is appropriate to take the word >> conforming to mean what is both stated and intended by the authors >> as its meaning; to do otherwise would go against both the letter >> and the spirit of what the Standard embodies. >> >>> Thus, you may perhaps be able to claim that you conform to the C >>> standard (quoting a specific standard number), but to call it also >>> a "C Compiler" may well impose some "higher" standards (namely >>> that it at least sort of does what it says it does). >> >> The question of whether such an implementation is conforming >> is exactly the question under discussion. That comes straight >> out of your posting at the start of this subthread (and still >> appearing in the quoted portion above). > > Note, the message I replied to brought up the concept of a court > of law and a "language lawyer", so I suspect that the script > implementation could be found guilty of not being a conforming C > compiler, not be cause it isn't conforming, but because it isn't > a C compiler in the first place (so conformance doesn't really > matter). > > In the case of free, (and a number of other functions), the > standard provides a (crude) description of the behavior of the > abstract machine. It says what the function should attempt to > do, while allowing it to fail, for unspecified reasons. I would > claim that an implementation that gratuitously fails has not met > the requirements of the abstract machine, and thus has hit > non-conformance. An environment might not provide for a heap, > and thus an implementation might be able to legitimately have a > malloc() that always returns NULL and be conforming. Once the > implementation admits that malloc() can in fact allocate some > memory, free is described as returning that memory for the > possibility of further allocation, so to not do this is > non-conforming. The problem is the Standard imposes no requirements for what constitutes "attempting" to allocate memory, and certainly none that are detectable through observable behavior. In effect what you are arguing is that the implementor's state of mind makes a difference in whether an implementation is conforming. How the Standard defines conformance makes it clear that it does not.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2014-03-31 11:18 -0400 |
| Message-ID | <53398728.8060303@verizon.net> |
| In reply to | #42342 |
On 03/29/2014 10:27 PM, Richard Damon wrote: > On 3/29/14, 7:11 PM, Tim Rentsch wrote: ... >> An attorney arguing that point of view would have a significant >> uphill battle. Section 5.1.2.3 p6 spells out pretty clearly what >> the bar is for being a conforming implementation, and it depends >> only on externally observable behavior, not on any implementation >> internal details. Moreover if any member of the WG14 committee >> were called to offer expert testimony in the case, I'm confident >> their testimony would be that such questions are concerned only >> with quality of implementation, and so are deliberately outside >> of what the Standard considers in defining conformance. >> > > Actually, since that clause specifies that the output be correct > according to what the abstract semantics would have produced, and the > definition of free is to make the memory available for further > allocations, this clause can NOT be used to excuse a reasonable reading > to require free to at least attempt something. > > As to being merely quality of implementations, most jurisdictions have > laws that require products to have at least certain very minimal levels > of quality to be offered. A conforming implementation of C might might have quality so low that it violates a particular jurisdiction's legal requirements for merchantability; but that implementation could not be correctly described as having falsely claimed to be a fully conforming. > After all, would YOU allow someone to say the following is a C compiler: > a shell script that checked if a file matches a specific sample, if it > matches copy another file to a specified place, and if not print a message? > > By a strict reading of the standard, such a script (with appropriate > documentation) seems to meet all that the standard requires. After all, > 5.2.4.1 only requires the ability to execute "at least one program ...", > and may (because there is no other requirement) indicate that any other > program for any reason doesn't meet the translation limits. There is a > footnote (non-normative) to avoid fixed limits whenever possible, but > that is 1) not normative, and 2) doesn't actually require anything. Not quite: a #error directive that survives conditional compilation must result in a diagnostic message that contains precisely specified contents (6.10.5). Since conforming implementations are prohibited from successfully translating such a translation unit (4p4), the fact that they are only required to successfully translate and execute one program does not exempt them from the requirements of 6.10.5. Whether or not the #error directive survives conditional compilation, and the exact text of that message, can only be determined with certainty by implementing fully translation phases 1-4. In particular, evaluation of #if conditions requires also implementing an extremely limited subset of phase 7 processing. Still, your basic point remains. Primarily due to 5.2.4.1, a minimally conforming implementation of C can be far too minimal to be of any practical use.
[toc] | [prev] | [next] | [standalone]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2014-03-21 03:31 +0000 |
| Message-ID | <lggbrb$a9$1@speranza.aioe.org> |
| In reply to | #42026 |
partremmaps@gmail.com wrote: (snip) > Do we at least agree that it is most likely that the standard > authors did fully intend (for a hosted environment) for malloc() > and friends to allocate if they can, and for free() to free the > pointed to memory further allocation? (snip) As defined by K&R, it was intended for smaller machines without garbage collection. Some other languages popular on those machines provided no dynamic allocation at all. Now, by the time that the ANSI standard was written, machines were getting larger, and garbage collection was known, though maybe not so efficient. Even though machines were larger, they weren't so large that you could ignore memory usage and not so fast that you could ignore efficiency. We now have many languages designed to be interpreted, and to allow the user not to have to worry about memory usage. (Mathematica, R, Matlab, to name a few). C isn't one of them. Presumably one could write a C interpreter, but it isn't usual. -- glen
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2014-03-29 15:39 -0700 |
| Message-ID | <kfnd2h4k4t1.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #42026 |
partremmaps@gmail.com writes: > This discussion has been most fascinating to me because I sort of > expected that several thinking people would look at the same > evidence (the written standard) and come to pretty close the same > conclusion. > > My desire for some level of agreement is that as long as we seem > to disagree it means some of us don't understand the topic, and > chances are that it's me since by far I'm sure you're all smarter > than I. However, I'm trying my very best to understand the > standard and it generally makes sense, and yet the conclusion I > arrive at seems different. > > Putting aside technical wording traps, > > Do we at least agree that it is most likely that the standard > authors did fully intend (for a hosted environment) for malloc() > and friends to allocate if they can, and for free() to free the > pointed to memory further allocation? I'd like to offer a different kind of answer, in hopes of getting at what I think it the real underlying issue here. How you're thinking about the question is off in an essential way, namely, you think the Standard is meant to address the question you're asking, whereas it really isn't. The authors of the C standard (IIANM going all the way back to the original ANSI committee) made a conscious choice /not/ to address questions regarding "quality of implementation" but only hard-edged questions with yes/no answers. Furthermore whether or not an implementation is conforming depends only on its behavior (plus the required supporting documentation), not on any internal details, except insofar as they have an impact on the required behavior. Your question about free() (and indirectly about malloc()) is a quality-of-implementation question, not a conformance question. There is no requirement that malloc() succeed at allocating memory, under any circumstances. It's perfectly legal for malloc() to consult a random number generator, even one that isn't deterministic, and always return NULL if the random number is, say, even. Similarly, it's perfectly legal for malloc() to initialize all free space as "not yet been allocated", and then let an allocation fail if memory that it otherwise would allocate has been marked as previously allocated. Obviously the effect is just the same as what would happen if free() had an empty function body. Your question about free() is a QOI question because really what it boils down to is, is how free() and malloc() are implemented "good enough"? The Standard chooses deliberately not to address such questions. So in answer to your question above, whatever various authors and WG14 committee members, not to mention other people who may have participated in meetings of WG14, might think about how free() will or should be implemented, they are essentially unanimous in the opinion that this question is one the Standard simply _does not address_, and in fact has chosen consciously not to address, because that purpose isn't one the Standard is meant to serve. The above may be summarized briefly as: The Standard does not define what constitutes a /good/ implementation, only what constitutes a /conforming/ implementation. Your question about free() and malloc() is really a question about how good their impelementations are, and therefore is outside what the Standard attempts to define.
[toc] | [prev] | [next] | [standalone]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2014-03-30 04:22 +0000 |
| Message-ID | <lh866o$e4t$1@speranza.aioe.org> |
| In reply to | #42328 |
Tim Rentsch <txr@alumni.caltech.edu> wrote: > partremmaps@gmail.com writes: (snip) >> Do we at least agree that it is most likely that the standard >> authors did fully intend (for a hosted environment) for malloc() >> and friends to allocate if they can, and for free() to free the >> pointed to memory further allocation? > I'd like to offer a different kind of answer, in hopes of getting > at what I think it the real underlying issue here. > How you're thinking about the question is off in an essential > way, namely, you think the Standard is meant to address the > question you're asking, whereas it really isn't. The authors of > the C standard (IIANM going all the way back to the original ANSI > committee) made a conscious choice /not/ to address questions > regarding "quality of implementation" but only hard-edged > questions with yes/no answers. Furthermore whether or not an > implementation is conforming depends only on its behavior (plus > the required supporting documentation), not on any internal > details, except insofar as they have an impact on the required > behavior. which allows for a variety of possible implementations. > Your question about free() (and indirectly about malloc()) is a > quality-of-implementation question, not a conformance question. > There is no requirement that malloc() succeed at allocating > memory, under any circumstances. It's perfectly legal for > malloc() to consult a random number generator, even one that > isn't deterministic, and always return NULL if the random number > is, say, even. More commonly, run on a system where other programs are randomly allocating memory, such that the available memory changes randomly. > Similarly, it's perfectly legal for malloc() to > initialize all free space as "not yet been allocated", and then > let an allocation fail if memory that it otherwise would allocate > has been marked as previously allocated. Obviously the effect is > just the same as what would happen if free() had an empty > function body. Your question about free() is a QOI question > because really what it boils down to is, is how free() and > malloc() are implemented "good enough"? The Standard chooses > deliberately not to address such questions. As I previously noted, though I haven't personally noticed, it seems that some systems now have "lazy allocation" where malloc() always returns non-null (with a 64 bit address space, you can do that for a long time) and later figures out if there is enough memory to allocate. That is, similar to the way airlines overbook, hoping that not everyone will show up. Early virtual memory systems allocated in virtual memory, such that they would return null even if plenty of real memory was available. Most now (even though disks are now bigger) aren't that restrictive. > So in answer to your question above, whatever various authors and > WG14 committee members, not to mention other people who may have > participated in meetings of WG14, might think about how free() > will or should be implemented, they are essentially unanimous in > the opinion that this question is one the Standard simply _does > not address_, and in fact has chosen consciously not to address, > because that purpose isn't one the Standard is meant to serve. > The above may be summarized briefly as: The Standard does not > define what constitutes a /good/ implementation, only what > constitutes a /conforming/ implementation. Your question about > free() and malloc() is really a question about how good their > impelementations are, and therefore is outside what the > Standard attempts to define. -- glen
[toc] | [prev] | [standalone]
Page 3 of 3 — ← Prev page 1 2 [3]
Back to top | Article view | comp.lang.c
csiph-web