Experiment: functional concepts in C

  • Follow


Hello people,

I thought it would be funny to try to bring functional concepts into the
C language.  If anyone is interested, I have published the results on my
blog [1].

[1] http://blog.ertes.de/2008/11/obscure-c-from-new-perspective.html


Greets,
Ertugrul.


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)

0
Reply es1 (159) 11/17/2008 11:43:14 AM

On 17 Nov, 11:43, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
> Hello people,
>
> I thought it would be funny to try to bring functional concepts into the
> C language.  If anyone is interested, I have published the results on my
> blog [1].
>
> [1]http://blog.ertes.de/2008/11/obscure-c-from-new-perspective.html


your code seems to have no whitespace in it including newlines.
I can't be bothered to re-layout it to make it readable.

(it could be a problem with my browser of course)

ah. It looks ok if I look at the source. It isn't HTML

--
Nick Keighley

0
Reply nick_keighley_nospam (4574) 11/17/2008 12:49:30 PM


On Nov 17, 1:43 pm, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
> Hello people,
>
> I thought it would be funny to try to bring functional concepts into the
> C language.  If anyone is interested, I have published the results on my
> blog [1].
>
> [1] http://blog.ertes.de/2008/11/obscure-c-from-new-perspective.html

Well your blog entry starts with

> C is probably the most uninteresting programming language in the world.

which is untrue and a bad way to start an article.

Reading further, in your code
<http://ertes.de/cfact/cfact1.c>

It seems you want to obfuscate your code, since you have things like

> puts("_Expecting one argument.\0Invalid integer." + jv); /* vippstar: jv =
is return value of setjmp */

Line 34 you return a value other than 0, EXIT_SUCCESS and
EXIT_FAILURE, which doesn't need to be meaningful.

The other 3 source files (cfact[2,3,4].c) are not standard C.
0
Reply vippstar (1211) 11/17/2008 12:57:00 PM

Ertugrul Söylemez <es@ertes.de> writes:
> Hello people,
>
> I thought it would be funny to try to bring functional concepts into the
> C language.  If anyone is interested, I have published the results on my
> blog [1].
>
> [1] http://blog.ertes.de/2008/11/obscure-c-from-new-perspective.html

"I have written four versions of the factorial function in C
[...]
Version 2 — using function pointer continuations"

 [ which contains:
    void fact(int x, void (*e)(char *), void (*k)(int)) {
        void mulCont(int y) {
            k(x*y);
        }
   ... ]

Version 3 — implementing algebraic lists and folds using closures

 [ which contains:
     void cons(int x, list xs, void (*k)(list)) {
         void concat(void (*end)(), void (*more)(int)) {
             more(x);
             xs(end, more);
         }
   ... ]

Version 4 — lambda calculus with fixpoint operator

 [ which contains:
     void fix(int (*f)(int (*)(int), int), void (*k)(int (*)(int))) {
         int ldf(int x) {
             int y;
   ... ]
"""


Perhaps you'd like to reword the introduction to say "I have written
four versions of the factorial function, one of which is in C and 
the rest of them are not in C."?

Phil
-- 
I tried the Vista speech recognition by running the tutorial. I was 
amazed, it was awesome, recognised every word I said. Then I said the 
wrong word ... and it typed the right one. It was actually just 
detecting a sound and printing the expected word! -- pbhj on /.
0
Reply thefatphil_demunged (1558) 11/17/2008 1:04:30 PM

In article <c7d8bd66-adb5-4485-8ff0-edf92b652667@q30g2000prq.googlegroups.com>,
Nick Keighley  <nick_keighley_nospam@hotmail.com> wrote:
>On 17 Nov, 11:43, Ertugrul S�ylemez <e...@ertes.de> wrote:
>> Hello people,
>>
>> I thought it would be funny to try to bring functional concepts into the
>> C language.  If anyone is interested, I have published the results on my
>> blog [1].
>>
>> [1]http://blog.ertes.de/2008/11/obscure-c-from-new-perspective.html
>
>
>your code seems to have no whitespace in it including newlines.
>I can't be bothered to re-layout it to make it readable.
>
>(it could be a problem with my browser of course)

It displays fine in lynx.  You should try it.

>ah. It looks ok if I look at the source. It isn't HTML

It displays fine in lynx.  You should try it.

Note to vippy: Of course it isn't standard C.  That is stipulated early
on.

0
Reply gazelle3 (1598) 11/17/2008 1:48:42 PM

vippstar@gmail.com wrote:
> On Nov 17, 1:43 pm, Ertugrul S�ylemez <e...@ertes.de> wrote:


> Reading further, in your code
> <http://ertes.de/cfact/cfact1.c>
>
> It seems you want to obfuscate your code, since you have things like
>
>> puts("_Expecting one argument.\0Invalid integer." + jv); /*
>> vippstar: jv is return value of setjmp */


I had a look to see if the OP had really put in the comment just for your 
benefit. He hadn't.

-- 
Bartc 

0
Reply bc (2211) 11/17/2008 2:12:25 PM

In article <c7d8bd66-adb5-4485-8ff0-edf92b652667@q30g2000prq.googlegroups.com>,
Nick Keighley  <nick_keighley_nospam@hotmail.com> wrote:

>your code seems to have no whitespace in it including newlines.
>I can't be bothered to re-layout it to make it readable.
>
>(it could be a problem with my browser of course)
>
>ah. It looks ok if I look at the source. It isn't HTML

It's served with the mime type text/x-csrc.  If your browser
treats that as HTML, it does indeed have a problem.

(My browser sensibly opens it in emacs.)

-- Richard
-- 
Please remember to mention me / in tapes you leave behind.
0
Reply richard91 (3683) 11/17/2008 2:33:05 PM

Ertugrul S=C3=B6ylemez <es@ertes.de> wrote:

> [...]

Yes, the latter three solutions are not standard C, but I pointed this
out in the article.  Implementing closures without this GCC extension is
near to impossible without implementing full garbage collection and some
notion of 'thunks'.  About the blog entry starting, vippstar, you're
right.  I adjusted it.

Thank you all for your comments.


Greets,
Ertugrul.


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)

0
Reply es1 (159) 11/17/2008 3:28:37 PM

vippstar@gmail.com wrote:

> Reading further, in your code
> <http://ertes.de/cfact/cfact1.c>
>
> It seems you want to obfuscate your code, since you have things like
>
> > puts("_Expecting one argument.\0Invalid integer." + jv); /*
> > vippstar: jv is return value of setjmp */

Yes, the first version was indeed just a funny thing, which started it
all.  I'm not happy with the result though, because of what you
mentioned.

The latter three versions, those which are not standard C, are more
interesting.  They implement something, which is totally natural in
functional languages, but which turns an imperative language into a
comprehensibility hell, without needing to artifically obfuscate code
like in the first version.  I'd love to implement them in standard C,
but as said in another post and in the blog, that was almost impossible.


Greets,
Ertugrul.


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)

0
Reply es1 (159) 11/17/2008 3:36:10 PM

On Nov 17, 5:36 pm, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
> vipps...@gmail.com wrote:
> > Reading further, in your code
> > <http://ertes.de/cfact/cfact1.c>
>
> > It seems you want to obfuscate your code, since you have things like
>
> > > puts("_Expecting one argument.\0Invalid integer." + jv); /*
> > > vippstar: jv is return value of setjmp */
>
> Yes, the first version was indeed just a funny thing, which started it
> all.  I'm not happy with the result though, because of what you
> mentioned.
>
> The latter three versions, those which are not standard C, are more
> interesting.  They implement something, which is totally natural in
> functional languages, but which turns an imperative language into a
> comprehensibility hell, without needing to artifically obfuscate code
> like in the first version.  I'd love to implement them in standard C,
> but as said in another post and in the blog, that was almost impossible.

The reason I mentioned the other three sources are not standard C is
because I did not comment on them.
If it's discussion/proposal for new C features, comp.lang.c is not the
right newsgroup. (comp.std.c would be better)
At most, your original message classifies as spam. Moreover, it's
usually better to just publish your article on usenet instead of
providing a web link.
0
Reply vippstar (1211) 11/17/2008 3:52:15 PM

vippstar@gmail.com writes:

> On Nov 17, 1:43 pm, Ertugrul Söylemez <e...@ertes.de> wrote:
>> Hello people,
>>
>> I thought it would be funny to try to bring functional concepts into the
>> C language.  If anyone is interested, I have published the results on my
>> blog [1].
>>
>> [1] http://blog.ertes.de/2008/11/obscure-c-from-new-perspective.html
>
> Well your blog entry starts with
>
>> C is probably the most uninteresting programming language in the world.
>
> which is untrue and a bad way to start an article.

You have misquoted the OP by omitting the subordinate clause and making
the main clause a sentence standing on its own.  The original text is,
for those who are too lazy to read the article,

"C is probably one of the most uninteresting programming languages in
the world, *from a language theory standpoint.*"
0
Reply sgm1 (1) 11/17/2008 3:52:28 PM

vippstar@gmail.com writes:

> At most, your original message classifies as spam.

No, his original message doesn't. At worst the post classifies as
off-topic.

-- 
Aatu Koskensilta (aatu.koskensilta@uta.fi)

"Wovon man nicht sprechen kann, darüber muss man schweigen"
 - Ludwig Wittgenstein, Tractatus Logico-Philosophicus
0
Reply aatu.koskensilta1 (232) 11/17/2008 4:17:30 PM

sgm@Pavilion.domain.invalid (Sean G. McLaughlin) wrote:

> vippstar@gmail.com writes:
>
> > Well your blog entry starts with
> >
> >> C is probably the most uninteresting programming language in the
> >> world.
> >
> > which is untrue and a bad way to start an article.
>
> You have misquoted the OP by omitting the subordinate clause and
> making the main clause a sentence standing on its own.  The original
> text is, for those who are too lazy to read the article,
>
> "C is probably one of the most uninteresting programming languages in
> the world, *from a language theory standpoint.*"

No, no, I added this later in response to vippstar's comment, and I
pointed this out here.  Sorry for the confusion.


Greets,
Ertugrul.


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)

0
Reply es1 (159) 11/17/2008 4:25:40 PM

On Nov 17, 7:57=A0am, vippstar@gmail.com wrote:
> Line 34 you return a value other than 0, EXIT_SUCCESS and
> EXIT_FAILURE, which doesn't need to be meaningful.

Whether the return status is meaningful or not is completely dependent
on the environment that executes the program. Even 0, EXIT_SUCCESS and
EXIT_FAILURE might not be meaningful (though, at least for 0, this
would be very rare).

> The other 3 source files (cfact[2,3,4].c) are not standard C.

Unsurprisingly, considering that the original post talked about
"bringing functional concepts into the C language."

Sebastian

0
Reply s0suk3 (372) 11/17/2008 8:27:25 PM

s0suk3@gmail.com writes:
> On Nov 17, 7:57�am, vippstar@gmail.com wrote:
>> Line 34 you return a value other than 0, EXIT_SUCCESS and
>> EXIT_FAILURE, which doesn't need to be meaningful.
>
> Whether the return status is meaningful or not is completely dependent
> on the environment that executes the program. Even 0, EXIT_SUCCESS and
> EXIT_FAILURE might not be meaningful (though, at least for 0, this
> would be very rare).

They're meaningful for any conforming hosted C implementation.  Can
you cite an implementation where they're not?

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 11/17/2008 8:46:49 PM

On Nov 17, 3:46=A0pm, Keith Thompson <kst-u@mib.org> wrote:
> s0suk3@gmail.com writes:
> > On Nov 17, 7:57=A0am, vippstar@gmail.com wrote:
> >> Line 34 you return a value other than 0, EXIT_SUCCESS and
> >> EXIT_FAILURE, which doesn't need to be meaningful.
>
> > Whether the return status is meaningful or not is completely dependent
> > on the environment that executes the program. Even 0, EXIT_SUCCESS and
> > EXIT_FAILURE might not be meaningful (though, at least for 0, this
> > would be very rare).
>
> They're meaningful for any conforming hosted C implementation.

Then there is no conforming hosted C implementation. No compiler could
possibly predict how all the programs in a system will interpret exit
codes from other programs.

Note: When I said "environment" in my previous post, I didn't just
mean the operating system. Any program can execute another program and
interpret its exit status however it wants.

Sebastian

0
Reply s0suk3 (372) 11/17/2008 9:07:24 PM

Since this is no longer relevant to comp.lang.functional, I'm
redirecting followups.

s0suk3@gmail.com writes:
> On Nov 17, 3:46�pm, Keith Thompson <kst-u@mib.org> wrote:
>> s0suk3@gmail.com writes:
>> > On Nov 17, 7:57�am, vippstar@gmail.com wrote:
>> >> Line 34 you return a value other than 0, EXIT_SUCCESS and
>> >> EXIT_FAILURE, which doesn't need to be meaningful.
>>
>> > Whether the return status is meaningful or not is completely dependent
>> > on the environment that executes the program. Even 0, EXIT_SUCCESS and
>> > EXIT_FAILURE might not be meaningful (though, at least for 0, this
>> > would be very rare).
>>
>> They're meaningful for any conforming hosted C implementation.
>
> Then there is no conforming hosted C implementation. No compiler could
> possibly predict how all the programs in a system will interpret exit
> codes from other programs.
>
> Note: When I said "environment" in my previous post, I didn't just
> mean the operating system. Any program can execute another program and
> interpret its exit status however it wants.

Every hosted system I'm familiar with has a convention for
interpreting status codes.  For example, Unix uses 0 for success, and
OpenVMS uses odd numbers for success.  Certainly there's nothing
preventing any individual program running on such a system from
violating those conventions -- but so what?  The command line
interpreter (e.g., the shell on Unix) is required to follow the
conventions; see, for example, the behavior of the "if" and "while"
statements in the Bourne shell.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 11/17/2008 9:14:46 PM

On Nov 17, 4:14=A0pm, Keith Thompson <kst-u@mib.org> wrote:
> Since this is no longer relevant to comp.lang.functional, I'm
> redirecting followups.
>
> s0suk3@gmail.com writes:
> > On Nov 17, 3:46=A0pm, Keith Thompson <kst-u@mib.org> wrote:
> >> s0suk3@gmail.com writes:
> >> > On Nov 17, 7:57=A0am, vippstar@gmail.com wrote:
> >> >> Line 34 you return a value other than 0, EXIT_SUCCESS and
> >> >> EXIT_FAILURE, which doesn't need to be meaningful.
>
> >> > Whether the return status is meaningful or not is completely depende=
nt
> >> > on the environment that executes the program. Even 0, EXIT_SUCCESS a=
nd
> >> > EXIT_FAILURE might not be meaningful (though, at least for 0, this
> >> > would be very rare).
>
> >> They're meaningful for any conforming hosted C implementation.
>
> > Then there is no conforming hosted C implementation. No compiler could
> > possibly predict how all the programs in a system will interpret exit
> > codes from other programs.
>
> > Note: When I said "environment" in my previous post, I didn't just
> > mean the operating system. Any program can execute another program and
> > interpret its exit status however it wants.
>
> Every hosted system I'm familiar with has a convention for
> interpreting status codes.

Exactly. They're conventions, not rules (at least not usually).

>=A0For example, Unix uses 0 for success, and
> OpenVMS uses odd numbers for success. =A0Certainly there's nothing
> preventing any individual program running on such a system from
> violating those conventions -- but so what?=A0The command line
> interpreter (e.g., the shell on Unix) is required to follow the
> conventions; see, for example, the behavior of the "if" and "while"
> statements in the Bourne shell.

It acts as a scripting language interpreter so it's obvious that it
will follow those conventions. But there might be other (OS native)
kinds of program launchers; for example, how about a GUI file browser
(such as KDE's Dolphin or Windows' "My PC")? For such launchers the
return codes will be less important. I at least have never heard about
how they interpret return codes, but if they do, they'll probably have
more freedom in choosing how to interpret them (and they may do so in
an unconventional way).

Sebastian

0
Reply s0suk3 (372) 11/17/2008 9:43:33 PM

s0suk3@gmail.com writes:
> On Nov 17, 4:14�pm, Keith Thompson <kst-u@mib.org> wrote:
>> Since this is no longer relevant to comp.lang.functional, I'm
>> redirecting followups.
>>
>> s0suk3@gmail.com writes:
>> > On Nov 17, 3:46�pm, Keith Thompson <kst-u@mib.org> wrote:
>> >> s0suk3@gmail.com writes:
>> >> > On Nov 17, 7:57�am, vippstar@gmail.com wrote:
>> >> >> Line 34 you return a value other than 0, EXIT_SUCCESS and
>> >> >> EXIT_FAILURE, which doesn't need to be meaningful.
>>
>> >> > Whether the return status is meaningful or not is completely dependent
>> >> > on the environment that executes the program. Even 0, EXIT_SUCCESS and
>> >> > EXIT_FAILURE might not be meaningful (though, at least for 0, this
>> >> > would be very rare).
>>
>> >> They're meaningful for any conforming hosted C implementation.
>>
>> > Then there is no conforming hosted C implementation. No compiler could
>> > possibly predict how all the programs in a system will interpret exit
>> > codes from other programs.
>>
>> > Note: When I said "environment" in my previous post, I didn't just
>> > mean the operating system. Any program can execute another program and
>> > interpret its exit status however it wants.
>>
>> Every hosted system I'm familiar with has a convention for
>> interpreting status codes.
>
> Exactly. They're conventions, not rules (at least not usually).
>
>>�For example, Unix uses 0 for success, and
>> OpenVMS uses odd numbers for success. �Certainly there's nothing
>> preventing any individual program running on such a system from
>> violating those conventions -- but so what?�The command line
>> interpreter (e.g., the shell on Unix) is required to follow the
>> conventions; see, for example, the behavior of the "if" and "while"
>> statements in the Bourne shell.
>
> It acts as a scripting language interpreter so it's obvious that it
> will follow those conventions. But there might be other (OS native)
> kinds of program launchers; for example, how about a GUI file browser
> (such as KDE's Dolphin or Windows' "My PC")? For such launchers the
> return codes will be less important. I at least have never heard about
> how they interpret return codes, but if they do, they'll probably have
> more freedom in choosing how to interpret them (and they may do so in
> an unconventional way).

Certainly an application that invokes another program can do whatever
it likes, or do nothing, with the returned status.

But here's what the standard says (C99 7.20.4.3p5, describing the
exit() function):

    Finally, control is returned to the host environment. If the value
    of status is zero or EXIT_SUCCESS, an implementation-defined form
    of the status _successful termination_ is returned. If the value
    of status is EXIT_FAILURE, an implementation-defined form of the
    status _unsuccessful termination) is returned. Otherwise the
    status returned is implementation-defined.

Will you at least agree that returning a value of zero, EXIT_SUCCESS,
or EXIT_FAILURE is more meaningful, as far as the C language
requirements are concerned, than returning other values?

If not, I don't think there's anything more to be said.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 11/18/2008 12:09:14 AM

On Nov 17, 7:09=A0pm, Keith Thompson <kst-u@mib.org> wrote:
> s0suk3@gmail.com writes:
> > On Nov 17, 4:14=A0pm, Keith Thompson <kst-u@mib.org> wrote:
> >> Since this is no longer relevant to comp.lang.functional, I'm
> >> redirecting followups.
>
> >> s0suk3@gmail.com writes:
> >> > On Nov 17, 3:46=A0pm, Keith Thompson <kst-u@mib.org> wrote:
> >> >> s0suk3@gmail.com writes:
> >> >> > On Nov 17, 7:57=A0am, vippstar@gmail.com wrote:
> >> >> >> Line 34 you return a value other than 0, EXIT_SUCCESS and
> >> >> >> EXIT_FAILURE, which doesn't need to be meaningful.
>
> >> >> > Whether the return status is meaningful or not is completely depe=
ndent
> >> >> > on the environment that executes the program. Even 0, EXIT_SUCCES=
S and
> >> >> > EXIT_FAILURE might not be meaningful (though, at least for 0, thi=
s
> >> >> > would be very rare).
>
> >> >> They're meaningful for any conforming hosted C implementation.
>
> >> > Then there is no conforming hosted C implementation. No compiler cou=
ld
> >> > possibly predict how all the programs in a system will interpret exi=
t
> >> > codes from other programs.
>
> >> > Note: When I said "environment" in my previous post, I didn't just
> >> > mean the operating system. Any program can execute another program a=
nd
> >> > interpret its exit status however it wants.
>
> >> Every hosted system I'm familiar with has a convention for
> >> interpreting status codes.
>
> > Exactly. They're conventions, not rules (at least not usually).
>
> >>=A0For example, Unix uses 0 for success, and
> >> OpenVMS uses odd numbers for success. =A0Certainly there's nothing
> >> preventing any individual program running on such a system from
> >> violating those conventions -- but so what?=A0The command line
> >> interpreter (e.g., the shell on Unix) is required to follow the
> >> conventions; see, for example, the behavior of the "if" and "while"
> >> statements in the Bourne shell.
>
> > It acts as a scripting language interpreter so it's obvious that it
> > will follow those conventions. But there might be other (OS native)
> > kinds of program launchers; for example, how about a GUI file browser
> > (such as KDE's Dolphin or Windows' "My PC")? For such launchers the
> > return codes will be less important. I at least have never heard about
> > how they interpret return codes, but if they do, they'll probably have
> > more freedom in choosing how to interpret them (and they may do so in
> > an unconventional way).
>
> Certainly an application that invokes another program can do whatever
> it likes, or do nothing, with the returned status.
>
> But here's what the standard says (C99 7.20.4.3p5, describing the
> exit() function):
>
> =A0 =A0 Finally, control is returned to the host environment. If the valu=
e
> =A0 =A0 of status is zero or EXIT_SUCCESS, an implementation-defined form
> =A0 =A0 of the status _successful termination_ is returned. If the value
> =A0 =A0 of status is EXIT_FAILURE, an implementation-defined form of the
> =A0 =A0 status _unsuccessful termination) is returned. Otherwise the
> =A0 =A0 status returned is implementation-defined.
>
> Will you at least agree that returning a value of zero, EXIT_SUCCESS,
> or EXIT_FAILURE is more meaningful, as far as the C language
> requirements are concerned, than returning other values?

Yes. And compilers will usually provide meaningful values for
EXIT_SUCCESS and EXIT_FAILURE.

But the point is not whether those values are meaningful or not; the
point is that compilers can't predict the kinds of applications that
will execute programs and interpret their return codes.

But yes, in general, 0, EXIT_SUCCESS and EXIT_FAILURE are reasonable
values to return, even though it can't be *guaranteed* that the parent
process will always interpret the status as you intended.

Sebastian

0
Reply s0suk3 (372) 11/18/2008 1:07:33 AM

s0suk3@gmail.com writes:
> On Nov 17, 7:09�pm, Keith Thompson <kst-u@mib.org> wrote:
[...]
>> Will you at least agree that returning a value of zero, EXIT_SUCCESS,
>> or EXIT_FAILURE is more meaningful, as far as the C language
>> requirements are concerned, than returning other values?
>
> Yes. And compilers will usually provide meaningful values for
> EXIT_SUCCESS and EXIT_FAILURE.
>
> But the point is not whether those values are meaningful or not;
[...]

Re-read the thread; that was exactly the point.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 11/18/2008 1:39:56 AM

On Nov 17, 8:39=A0pm, Keith Thompson <kst-u@mib.org> wrote:
> s0suk3@gmail.com writes:
> > On Nov 17, 7:09=A0pm, Keith Thompson <kst-u@mib.org> wrote:
> [...]
> >> Will you at least agree that returning a value of zero, EXIT_SUCCESS,
> >> or EXIT_FAILURE is more meaningful, as far as the C language
> >> requirements are concerned, than returning other values?
>
> > Yes. And compilers will usually provide meaningful values for
> > EXIT_SUCCESS and EXIT_FAILURE.
>
> > But the point is not whether those values are meaningful or not;
>
> [...]
>
> Re-read the thread; that was exactly the point.

OK, I should have said "meaningful in general" or "meaningful in
regard to the standard". Other than that, the point that the exit
status *can't* always be meaningful still remains.

Sebastian

0
Reply s0suk3 (372) 11/18/2008 1:50:39 AM

On 17 Nov, 16:17, Aatu Koskensilta <aatu.koskensi...@uta.fi> wrote:
> vipps...@gmail.com writes:

> > At most, your original message classifies as spam.
>
> No, his original message doesn't. At worst the post classifies as
> off-topic.

yes
0
Reply nick_keighley_nospam (4574) 11/18/2008 9:11:04 AM

On Nov 17, 10:46 pm, Keith Thompson <ks...@mib.org> wrote:
> s0s...@gmail.com writes:
> > On Nov 17, 7:57 am, vipps...@gmail.com wrote:
> >> Line 34 you return a value other than 0, EXIT_SUCCESS and
> >> EXIT_FAILURE, which doesn't need to be meaningful.
>
> > Whether the return status is meaningful or not is completely dependent
> > on the environment that executes the program. Even 0, EXIT_SUCCESS and
> > EXIT_FAILURE might not be meaningful (though, at least for 0, this
> > would be very rare).
>
> They're meaningful for any conforming hosted C implementation.  Can
> you cite an implementation where they're not?

He is a troll, why are you wasting your time?
0
Reply vippstar (1211) 11/18/2008 12:24:10 PM

In article <e2af0da5-ce04-47a2-941b-103a5cf338ba@r15g2000prh.googlegroups.com>,
 <vippstar@gmail.com> wrote:
>On Nov 17, 10:46 pm, Keith Thompson <ks...@mib.org> wrote:
>> s0s...@gmail.com writes:
>> > On Nov 17, 7:57 am, vipps...@gmail.com wrote:
>> >> Line 34 you return a value other than 0, EXIT_SUCCESS and
>> >> EXIT_FAILURE, which doesn't need to be meaningful.
>>
>> > Whether the return status is meaningful or not is completely dependent
>> > on the environment that executes the program. Even 0, EXIT_SUCCESS and
>> > EXIT_FAILURE might not be meaningful (though, at least for 0, this
>> > would be very rare).
>>
>> They're meaningful for any conforming hosted C implementation.  Can
>> you cite an implementation where they're not?
>
>He is a troll, why are you wasting your time?

Believe me in this: If there is one thing Keith Thompson has lots and
lots of, it is time (on his hands).

0
Reply gazelle3 (1598) 11/18/2008 2:34:02 PM

On Nov 18, 7:24=A0am, vippstar@gmail.com wrote:
> On Nov 17, 10:46 pm, Keith Thompson <ks...@mib.org> wrote:
>
> > s0s...@gmail.com writes:
> > > On Nov 17, 7:57 am, vipps...@gmail.com wrote:
> > >> Line 34 you return a value other than 0, EXIT_SUCCESS and
> > >> EXIT_FAILURE, which doesn't need to be meaningful.
>
> > > Whether the return status is meaningful or not is completely dependen=
t
> > > on the environment that executes the program. Even 0, EXIT_SUCCESS an=
d
> > > EXIT_FAILURE might not be meaningful (though, at least for 0, this
> > > would be very rare).
>
> > They're meaningful for any conforming hosted C implementation. =A0Can
> > you cite an implementation where they're not?
>
> He is a troll, why are you wasting your time?

I'd like to remind you of a thread, and especially of a particular
post:

http://groups.google.com/group/comp.lang.c/msg/7ce5393c60e40b19

where it was proven who of the two of us is a troll. (You yourself
admitted it; read the last line.)

Sebastian

0
Reply s0suk3 (372) 11/18/2008 5:57:52 PM

Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:

> On 17 Nov, 16:17, Aatu Koskensilta <aatu.koskensi...@uta.fi> wrote:
>
> > vipps...@gmail.com writes:
> >
> > > At most, your original message classifies as spam.
> >
> > No, his original message doesn't. At worst the post classifies as
> > off-topic.
>
> yes

Although I'm in some sense not entitled to judge, I wouldn't consider my
original post spam.  Since this is a C group, it's off-topic in that I'm
talking about implementing closures using non-standard GCC features.

This is true and fine and great and everything, but I'm very
disappointed by the responses, because all I got was being flamed off
for using extensions, not a single comment on the actual subject.
Nobody cared about the theoretical value in the (latter three) source
codes.  It feels like nobody of the original responders even read the
article -- where I pointed out that I used non-standard features! -- or
bothered about understanding the code.

By the way, people break standards all the time.  If standards limit you
in what you can do for no apparent reason, they are bound to be broken,
with POSIX probably being the best example, or do you GNU users set
POSIXLY_CORRECT?  I don't.  On the other hand, lexical closures in C
_are_ a bad extension, but being useful, fast and elegant wasn't the
point of my code anyway.  It was a theoretical experiment.


Greets,
Ertugrul.


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)

0
Reply es1 (159) 11/18/2008 8:25:52 PM

In article <20081118212552.14739638@ertes.de>,
Ertugrul Söylemez  <es@ertes.de> wrote:
....
>This is true and fine and great and everything, but I'm very
>disappointed by the responses, because all I got was being flamed off
>for using extensions, not a single comment on the actual subject.
>Nobody cared about the theoretical value in the (latter three) source
>codes.

That's all you'll ever get here (in clc).  It's the way it is.
They do this all over Usenet now - all they do is pick on you - because
there's just no psycho-sexual benefit to the poster for doing anything
else.  But it is worse here than anywhere else.

>It feels like nobody of the original responders even read the
>article -- where I pointed out that I used non-standard features! -- or
>bothered about understanding the code.

Welcome to CLC.  We hope you enjoy your stay.

>By the way, people break standards all the time.  If standards limit you
>in what you can do for no apparent reason, they are bound to be broken,
>with POSIX probably being the best example, or do you GNU users set
>POSIXLY_CORRECT?  I don't.  On the other hand, lexical closures in C
>_are_ a bad extension, but being useful, fast and elegant wasn't the
>point of my code anyway.  It was a theoretical experiment.

People here don't brook nonsense like "theoretical experiment"s.

0
Reply gazelle3 (1598) 11/18/2008 10:05:43 PM

On Nov 18, 10:25 pm, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
> Nick Keighley <nick_keighley_nos[80]...@hotmail.com> wrote:
> > On 17 Nov, 16:17, Aatu Koskensilta <aatu.koskensi[81]...@uta.fi> wrote:
>
> > > vipps[82]...@gmail.com writes:
>
> > > > At most, your original message classifies as spam.
>
> > > No, his original message doesn't. At worst the post classifies as
> > > off-topic.
>
> > yes

Hm... Yes what?

> Although I'm in some sense not entitled to judge, I wouldn't consider my
> original post spam.  Since this is a C group, it's off-topic in that I'm
> talking about implementing closures using non-standard GCC features.

Spam: off-topic message luring views.
Your post: interesting off-topic discussion seeking different POVs.
At worst: spam.

If you disagree, that's fine. I don't think it was such an important
statement nor an outrageous insult (nor an insult at all in fact) so
let's just move on.

> This is true and fine and great and everything, but I'm very
> disappointed by the responses, because all I got was being flamed off
> for using extensions, not a single comment on the actual subject.

You haven't been flamed yet, unless you see messages I don't.

> Nobody cared about the theoretical value in the (latter three) source
> codes.  It feels like nobody of the original responders even read the
> article -- where I pointed out that I used non-standard features! -- or
> bothered about understanding the code.

Because your message was off-topic. There's another possibility that
some cared, but chosen not to pollute this newsgroup with more off-
topic messages. Another reason to be on-topic.

> By the way, people break standards all the time.

True, but of little value. People break the law all the time as well -
that doesn't mean the law shouldn't exist, nor the opposite, that the
law is perfect.

> If standards limit you
> in what you can do for no apparent reason, they are bound to be broken,
> with POSIX probably being the best example, or do you GNU users set
> POSIXLY_CORRECT?  I don't.

The reason might not be apparent, but it exists. If you have any REAL
queries about the reason a feature was included/excluded from C, you
can ask here. For example, you could ask the reason the standard
doesn't require the execution environment to free the memory allocated
by malloc, realloc, calloc upon program termination. You'll probably
get an answer similar to "feature X couldn't be supported in system Y
- Y being old, new, future, imaginary system"

As for POSIXLY_CORRECT, well, that's another off-topic query. As far
as the C standard is concerned, POSIXLY_CORRECT is an identifier for
the programmer, not the implementation. What POSIX programmers should
actually do is a query for comp.unix.programmer, but since it's a
quick one:

IEEE-1003.1-2004:
<http://www.opengroup.org/onlinepubs/009695399/basedefs/
xbd_chap02.html>
> The system shall [...], and shall set the symbolic constant _POSIX_VERSIO=
N to the value 200112L.

An on-topic remark: _POSIX_VALUE is an identifier for the
implementation, because it starts with an underscore and that
underscore is followed by an uppercase letter.

> On the other hand, lexical closures in C
> _are_ a bad extension, but being useful, fast and elegant wasn't the
> point of my code anyway.  It was a theoretical experiment.

You've already been told this is off-topic. Please don't bring more
off-topic statements for fact-checking.
0
Reply vippstar (1211) 11/18/2008 10:08:24 PM

In article <b32b6712-4488-400d-898f-0e2ffd4bacdc@i18g2000prf.googlegroups.com>,
 <vippstar@gmail.com> wrote nothing of value:
<flushed>

You are such a tool...

0
Reply gazelle3 (1598) 11/18/2008 10:10:53 PM

vippstar@gmail.com writes:
> On Nov 18, 10:25 pm, Ertugrul S�ylemez <e...@ertes.de> wrote:
>> Nick Keighley <nick_keighley_nos[80]...@hotmail.com> wrote:
>> > On 17 Nov, 16:17, Aatu Koskensilta <aatu.koskensi[81]...@uta.fi> wrote:
>>
>> > > vipps[82]...@gmail.com writes:
>>
>> > > > At most, your original message classifies as spam.
>>
>> > > No, his original message doesn't. At worst the post classifies as
>> > > off-topic.
>>
>> > yes
>
> Hm... Yes what?
>
>> Although I'm in some sense not entitled to judge, I wouldn't consider my
>> original post spam.  Since this is a C group, it's off-topic in that I'm
>> talking about implementing closures using non-standard GCC features.
>
> Spam: off-topic message luring views.
> Your post: interesting off-topic discussion seeking different POVs.
> At worst: spam.

No, that's not what the word "spam" means.  Spam on Usenet is an
excessively cross-posted message; the most commonly accepted meaning
is anything that exceeds the Breidbart Index.  A single message posted
to a single newsgroup might be inappropriate, but it cannot be spam.

[...]

>> If standards limit you
>> in what you can do for no apparent reason, they are bound to be broken,
>> with POSIX probably being the best example, or do you GNU users set
>> POSIXLY_CORRECT?  I don't.
>
[...]
>
> As for POSIXLY_CORRECT, well, that's another off-topic query. As far
> as the C standard is concerned, POSIXLY_CORRECT is an identifier for
> the programmer, not the implementation. What POSIX programmers should
> actually do is a query for comp.unix.programmer, but since it's a
> quick one:
>
> IEEE-1003.1-2004:
> <http://www.opengroup.org/onlinepubs/009695399/basedefs/
> xbd_chap02.html>
>> The system shall [...], and shall set the symbolic constant _POSIX_VERSION to the value 200112L.
>
> An on-topic remark: _POSIX_VALUE is an identifier for the
> implementation, because it starts with an underscore and that
> underscore is followed by an uppercase letter.

<OT>That doesn't have much to do with POSIXLY_CORRECT, which is the
name of an environment variable, not a C identifier.</OT>

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 11/18/2008 11:05:19 PM

On Nov 19, 1:05 am, Keith Thompson <ks...@mib.org> wrote:
> vipps...@gmail.com writes:
> > Spam: off-topic message luring views.
>
> No, that's not what the word "spam" means.  Spam on Usenet is an
> excessively cross-posted message; the most commonly accepted meaning
> is anything that exceeds the Breidbart Index.  A single message posted
> to a single newsgroup might be inappropriate, but it cannot be spam.

I don't really want to argue with definitions for English words, but I
think the jargon file disagrees with you.
<http://catb.org/jargon/html/S/spam.html>
In particular, see 2, "this is _often_ done with cross-posting
[...]" (emphasis added by me)

<snip>
> <OT>That doesn't have much to do with POSIXLY_CORRECT, which is the
> name of an environment variable, not a C identifier.</OT>

Whatever POSIXLY_CORRECT is, it's defined in a standard other than C
(and for that matter, POSIX). C (and POSIX) says POSIXLY_CORRECT is an
identifier in the programmers namespace, which means he is under
complete control of what it is.
0
Reply vippstar (1211) 11/18/2008 11:44:11 PM

vippstar@gmail.com wrote:

> > This is true and fine and great and everything, but I'm very
> > disappointed by the responses, because all I got was being flamed
> > off for using extensions, not a single comment on the actual
> > subject.
>
> You haven't been flamed yet, unless you see messages I don't.

Your interpretation may be different.


> > Nobody cared about the theoretical value in the (latter three)
> > source codes.  It feels like nobody of the original responders even
> > read the article -- where I pointed out that I used non-standard
> > features! -- or bothered about understanding the code.
>
> Because your message was off-topic. There's another possibility that
> some cared, but chosen not to pollute this newsgroup with more off-
> topic messages. Another reason to be on-topic.

Being standards-compliant is one thing, simply being counter-innovative
is another.  What do we need comp.std.c for, if this newsgroup is about
and only about standard C, and if going beyond it is evil?  Where should
I post this instead?  In my opinion, this _is_ a C-related topic, at
least because it shows something that is difficult to implement in
standard C.

By the way, according to your view, GCC and most other compilers are not
C compilers.  They compile some language derived from C.


> > By the way, people break standards all the time.
>
> True, but of little value. People break the law all the time as well -
> that doesn't mean the law shouldn't exist, nor the opposite, that the
> law is perfect.

Your view appears to be that in a law-related newsgroup, one shouldn't
talk about the limits of law and/or about breaking it.


> > If standards limit you in what you can do for no apparent reason,
> > they are bound to be broken, with POSIX probably being the best
> > example, or do you GNU users set POSIXLY_CORRECT?  I don't.
>
> The reason might not be apparent, but it exists. If you have any REAL
> queries about the reason a feature was included/excluded from C, you
> can ask here.  [...]

This is a discussion forum, not a support forum.


> As for POSIXLY_CORRECT, well, that's another off-topic query.  [...]

That was not a query at all.


> > On the other hand, lexical closures in C _are_ a bad extension, but
> > being useful, fast and elegant wasn't the point of my code anyway.
> > It was a theoretical experiment.
>
> You've already been told this is off-topic. Please don't bring more
> off-topic statements for fact-checking.

You told me.  I'm unable to find any etiquette or posting rules.  This
is a C-related topic.  The group name suggests it's on-topic.


Greets,
Ertugrul.


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)

0
Reply es1 (159) 11/19/2008 12:48:37 AM

gazelle@shell.xmission.com (Kenny McCormack) wrote:

> In article <20081118212552.14739638@ertes.de>,
> Ertugrul S=C3=83=C2=B6ylemez  <es@ertes.de> wrote:
>
> > This is true and fine and great and everything, but I'm very
> > disappointed by the responses, because all I got was being flamed
> > off for using extensions, not a single comment on the actual
> > subject.  Nobody cared about the theoretical value in the (latter
> > three) source codes.
>
> That's all you'll ever get here (in clc).  It's the way it is.  They
> do this all over Usenet now [...]

I can't confirm that, but yes, I expected much more positive answers
here.  It seems that C is so uninteresting from a language-theoretic
standpoint that people are restricted to writing code and finding errors
in code (with using extensions being considererd one) rather than
talking a bit about the language itself and its design.  The latter was
my intention.

In the functional language world, for example, this is way different.
Those people generally welcome theoretical discussions, experiments and
even criticism about the language, because one of the key points of
functional programming is to improve our way of coding and even
thinking.  And it works.  I'd happily replace C as the system language
by any comparably low-level functional language.

By the way, the idea was inspired by The Evolution of a Haskell
Programmer [1].  I thought, it would be funny to try to implement some
of those examples in C.  Unfortunately C's type system is not
Turing-complete.  On the other hand, if I haven't overlooked something
obvious, with recursive #includes, the preprocessor is.

[1] http://www.willamette.edu/~fruehr/haskell/evolution.html


Greets,
Ertugrul.


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)

0
Reply es1 (159) 11/19/2008 1:12:57 AM

Ertugrul S�ylemez <es@ertes.de> writes:
> vippstar@gmail.com wrote:
>> > This is true and fine and great and everything, but I'm very
>> > disappointed by the responses, because all I got was being flamed
>> > off for using extensions, not a single comment on the actual
>> > subject.
>>
>> You haven't been flamed yet, unless you see messages I don't.
>
> Your interpretation may be different.
>
>> > Nobody cared about the theoretical value in the (latter three)
>> > source codes.  It feels like nobody of the original responders even
>> > read the article -- where I pointed out that I used non-standard
>> > features! -- or bothered about understanding the code.
>>
>> Because your message was off-topic. There's another possibility that
>> some cared, but chosen not to pollute this newsgroup with more off-
>> topic messages. Another reason to be on-topic.
>
> Being standards-compliant is one thing, simply being counter-innovative
> is another.  What do we need comp.std.c for, if this newsgroup is about
> and only about standard C, and if going beyond it is evil?  

You're confusing talking about the standard and talking about
programming using the standard. For example, I rarely have any 
interest in discussions about upcoming propositions and drafts
of the standard, so I don't generally hang aroung comp.std.c. 
Yet I have a strong interest in programming portable C, so I 
do hang around here. I don't see the two groups as being much 
more related than a French linguistics group is to a French 
chat group, or a beer-drinkers group is to a brewing group.

Phil
-- 
I tried the Vista speech recognition by running the tutorial. I was 
amazed, it was awesome, recognised every word I said. Then I said the 
wrong word ... and it typed the right one. It was actually just 
detecting a sound and printing the expected word! -- pbhj on /.
0
Reply thefatphil_demunged (1558) 11/19/2008 1:19:28 AM

Phil Carmody <thefatphil_demunged@yahoo.co.uk> wrote:

> Ertugrul S=C3=B6ylemez <es@ertes.de> writes:
>
> > Being standards-compliant is one thing, simply being
> > counter-innovative is another.  What do we need comp.std.c for, if
> > this newsgroup is about and only about standard C, and if going
> > beyond it is evil?
>
> You're confusing talking about the standard and talking about
> programming using the standard. For example, I rarely have any
> interest in discussions about upcoming propositions and drafts of the
> standard, so I don't generally hang aroung comp.std.c.  Yet I have a
> strong interest in programming portable C, so I do hang around here. I
> don't see the two groups as being much more related than a French
> linguistics group is to a French chat group, or a beer-drinkers group
> is to a brewing group.

There is of course nothing wrong with that.  Feel free not to
participate in this thread.

I'm talking both about the language and about programming in it (or how
doing certain things is difficult).  This discussion is, of course, by
no means productive, but as said, I never intended to contribute useful
code.  I thought, some people would like to discuss the theoretical
aspects of C, or at least find my code amusing.

After all, I could have written the same code without using extensions.
It's just that it would be ten times as long and ten times as
incomprehensible.


Greets,
Ertugrul.


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)

0
Reply es1 (159) 11/19/2008 1:39:47 AM

vippstar@gmail.com writes:
> On Nov 19, 1:05 am, Keith Thompson <ks...@mib.org> wrote:
>> vipps...@gmail.com writes:
>> > Spam: off-topic message luring views.
>>
>> No, that's not what the word "spam" means.  Spam on Usenet is an
>> excessively cross-posted message; the most commonly accepted meaning
>> is anything that exceeds the Breidbart Index.  A single message posted
>> to a single newsgroup might be inappropriate, but it cannot be spam.
>
> I don't really want to argue with definitions for English words,

.... and yet ...

>                                                                  but I
> think the jargon file disagrees with you.
> <http://catb.org/jargon/html/S/spam.html>
> In particular, see 2, "this is _often_ done with cross-posting
> [...]" (emphasis added by me)

I don't disagree with the jargon file; if you'll read the rest of the
entry, you'll see that the first two meanings have largely fallen into
disuses.

Meaning 2 describes what I'd call "trolling", i.e., posting something
inflammatory with the intent of starting an argument.  I don't think
that's what the OP intended to do.

> <snip>
>> <OT>That doesn't have much to do with POSIXLY_CORRECT, which is the
>> name of an environment variable, not a C identifier.</OT>
>
> Whatever POSIXLY_CORRECT is, it's defined in a standard other than C
> (and for that matter, POSIX).

I'm not sure that it's defined in any standard.  For purposes of this
newsgroup, it suffices to say that it's not defined in the C standard
(and nobody has suggested that it is).  The previous poster mentioned
POSIXLY_CORRECT in passing in the context of talking about conforming
or not conforming to standards.  (GNU software often doesn't quite
conform to POSIX by default; setting POSIXLY_CORRECT causes it to
conform more closely.)  It was a real-world example meant to
illustrate a point.

>                               C (and POSIX) says POSIXLY_CORRECT is an
> identifier in the programmers namespace, which means he is under
> complete control of what it is.

POSIXLY_CORRECT in this context *is not an identifier*.  It's the name
of an environment variable, which means it's a string whose address
you could pass to getenv().  If you want to mention that it's
off-topic, fine, but why go off on a tangent about how that particular
character string could be used as an identifier in a C program?

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 11/19/2008 2:44:23 AM

Ertugrul S�ylemez wrote:
> vippstar@gmail.com wrote:
....
> Being standards-compliant is one thing, simply being counter-innovative
> is another.  What do we need comp.std.c for, if this newsgroup is about
> and only about standard C,

comp.std.c is for discussions about the C standard. comp.lang.c is for 
discussions about how to use the language defined by that standard. 
Proposed changes to the standard are on-topic in comp.std.c, and 
off-topic in comp.lang.c. If you are talking about an extension to C 
that you do not propose standardizing, it's off-topic in both groups.

I have no idea what's on-topic in comp.lang.functional.

> ... and if going beyond it is evil?

Going beyond the standard isn't evil, just off-topic. You're wasting 
time (yours and other peoples) by discussing it here, just as you would 
be wasting time going to a butcher shop when you're trying to buy flowers.

....
> By the way, according to your view, GCC and most other compilers are not
> C compilers.  They compile some language derived from C.

gcc has a mode that fully-conforms to C90, making it definitely a C 
compiler when used in that mode. It has another mode that comes pretty 
close to fully conforming to C99. It is "almost" a C compiler when used 
in that mode.

....
>>> By the way, people break standards all the time.
>> True, but of little value. People break the law all the time as well -
>> that doesn't mean the law shouldn't exist, nor the opposite, that the
>> law is perfect.
> 
> Your view appears to be that in a law-related newsgroup, one shouldn't
> talk about the limits of law and/or about breaking it.

comp.std.c is the equivalent of a "law-related" group in this context, 
and discussion of changes to the standard would certainly be on-topic there.
0
Reply jameskuyper (5159) 11/19/2008 3:12:48 AM

Ertugrul S�ylemez <es@ertes.de> writes:
> I thought it would be funny to try to bring functional concepts into the
> C language.  If anyone is interested, I have published the results on my
> blog [1].
>
> [1] http://blog.ertes.de/2008/11/obscure-c-from-new-perspective.html

Of the four programs you posted, three of them depend on a
non-standard extension, namely nested function definitions.  As such,
they are, in my opinion, examples of using function concepts in a
C-like language (namely GNU C), not in C itself.  (I wonder if similar
things could be done using only standard C -- but I don't wonder
enough to spend a whole lot of time thinking about it.)

If you think that these three programs are an argument in favor of
adding features to C itself, then comp.std.c would be the best place
to make that argument.  I offer no opinion (at least for now) on
whether it would be a good idea.

Going back to the first program, it is in standard C, but some of the
coding is quite obscure.  For example, in one place you write:
    puts("_Expecting one argument.\0Invalid integer." + jv);
where jv has been set to either 1 or 25 in a call to longjmp.  Some
other problems I found:

Your factorial function is declared to return an int, but it doesn't
return a value, and the call doesn't attempt to use the returned
value.  (The result is returned via longjmp().)

You use the atoi() function, which invokes undefined behavior for
certain arguments.

Your variable names are unnecessarily terse.  You use the name "p"
both for a static int in the factorial function, and for a jmp_buf.
If you want to illustrate an unconventional technique, I think it's
best to make the rest of the code as clear as possible.

Here's my version of your program:

/* Factorial function using continuations in C.
 * Copyright (C) 2008, Ertugrul Söylemez
 * Modified by Keith Thompson
 */

#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>

enum error_code {
    no_error,
    bad_arg_count,
    invalid_integer
};

static char *errors[] = {
    /* no_error (unused) */ NULL, 
    /* bad_arg_count     */ "Expecting one argument.\n",
    /* invalid_integer   */ "Invalid integer.\n"
};


void factorial(int x, jmp_buf err, jmp_buf print) {
    static int product;
    jmp_buf recurse;
    int jv;

    product = 1;
    if (x < 0) longjmp(err, invalid_integer);
    jv = setjmp(recurse);
    if (!jv) longjmp(recurse, x);

    product *= jv;
    if (jv > 1) longjmp(recurse, jv-1);
    longjmp(print, product);
}


int main(int argc, char **argv) {
    jmp_buf err;
    jmp_buf print;
    int jv;
    int x;
    char *endptr;

    jv = setjmp(err);
    if (jv) {
        fputs(errors[jv], stderr);
        return EXIT_FAILURE;
    }

    jv = setjmp(print);
    if (jv) {
        printf("%d\n", jv);
        return 0;
    }

    if (argc != 2) {
        longjmp(err, bad_arg_count);
    }
    x = strtol(argv[1], &endptr, 10);
    if (argv[1][0] != '\0' && *endptr == '\0') {
        factorial(x, err, print);
    }
    else {
        longjmp(err, invalid_integer);
    }
}

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 11/19/2008 5:57:29 AM

In article <20081119014837.6018bf28@ertes.de>,
Ertugrul Söylemez  <es@ertes.de> wrote:

>Being standards-compliant is one thing, simply being counter-innovative
>is another.  What do we need comp.std.c for, if this newsgroup is about
>and only about standard C, and if going beyond it is evil?  Where should
>I post this instead?  In my opinion, this _is_ a C-related topic, at
>least because it shows something that is difficult to implement in
>standard C.

There is no agreement about what is topical in comp.lang.c.
Originally it was very broad, often including discussions about unix.
At some point several of the most prolific posters seem to have
decided that only discussion of standard C was acceptable.  If they
have succeeded in imposing this view, it is only by repeated
assertion, so they can have no complaint if the issue swings the other
way.

So if you feel (as I do) that discussion of improvements to C is
reasonable in comp.lang.c, I suggest that you just go ahead and
discuss them, and ignore the complaints.  Don't waste your time
arguing about topicality.

-- Richard
-- 
Please remember to mention me / in tapes you leave behind.
0
Reply richard91 (3683) 11/19/2008 9:24:35 AM

In article <ln63mk2r7a.fsf@nuthaus.mib.org>,
Keith Thompson  <kst-u@mib.org> wrote:

>If you think that these three programs are an argument in favor of
>adding features to C itself, then comp.std.c would be the best place
>to make that argument.

I think this is quite wrong.  It implies that there's no place for
discussion of extending C unless it's with a view to standardising it,
which would be absurdly premature in most cases.

There's a standard for C, but that doesn't mean that anything not
in the standard isn't C.

-- Richard
-- 
Please remember to mention me / in tapes you leave behind.
0
Reply richard91 (3683) 11/19/2008 9:27:47 AM

richard@cogsci.ed.ac.uk (Richard Tobin) writes:
> In article <ln63mk2r7a.fsf@nuthaus.mib.org>,
> Keith Thompson  <kst-u@mib.org> wrote:
>>If you think that these three programs are an argument in favor of
>>adding features to C itself, then comp.std.c would be the best place
>>to make that argument.
>
> I think this is quite wrong.  It implies that there's no place for
> discussion of extending C unless it's with a view to standardising it,
> which would be absurdly premature in most cases.
>
> There's a standard for C, but that doesn't mean that anything not
> in the standard isn't C.

When I say "adding features to C itself", I'm referring specifically
to making changes to the C standard.

You can add features to a C implementation, but then you're just
implementing extensions on top of C, not changing C itself.

Followups to comp.lang.c.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 11/19/2008 9:30:55 AM

In article <gg0m6j$2qn2$2@pc-news.cogsci.ed.ac.uk>,
Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
>In article <ln63mk2r7a.fsf@nuthaus.mib.org>,
>Keith Thompson  <kst-u@mib.org> wrote:
>
>>If you think that these three programs are an argument in favor of
>>adding features to C itself, then comp.std.c would be the best place
>>to make that argument.
>
>I think this is quite wrong.  It implies that there's no place for
>discussion of extending C unless it's with a view to standardising it,
>which would be absurdly premature in most cases.
>
>There's a standard for C, but that doesn't mean that anything not
>in the standard isn't C.

Uh oh.  You're in trouble now.

Expect massive flaming to be coming your way, from the likes of
KeithyWeithy and VippyVippy.

FWIW, and I may be wrong, but I thought you *were* one of the regs/butt-buddy
club.  Have you had a recent religious-experience/conversion?  If so,
praise the lord (I saw the light!)

0
Reply gazelle3 (1598) 11/19/2008 10:51:11 AM

richard@cogsci.ed.ac.uk (Richard Tobin) writes:
> In article <ln63mk2r7a.fsf@nuthaus.mib.org>,
> Keith Thompson  <kst-u@mib.org> wrote:
>
>>If you think that these three programs are an argument in favor of
>>adding features to C itself, then comp.std.c would be the best place
>>to make that argument.
>
> I think this is quite wrong.  It implies that there's no place for
> discussion of extending C unless it's with a view to standardising it,
> which would be absurdly premature in most cases.

You seem to be conflating the concepts of "extending C", and 
"coming up with your own C-like language". Extending C is 
changing C, i.e. modifying the standard that defines C. 

Phil
-- 
I tried the Vista speech recognition by running the tutorial. I was 
amazed, it was awesome, recognised every word I said. Then I said the 
wrong word ... and it typed the right one. It was actually just 
detecting a sound and printing the expected word! -- pbhj on /.
0
Reply thefatphil_demunged (1558) 11/19/2008 1:51:58 PM

In article <87y6zf7ri9.fsf@nonospaz.fatphil.org>,
Phil Carmody  <thefatphil_demunged@yahoo.co.uk> wrote:

>You seem to be conflating the concepts of "extending C", and 
>"coming up with your own C-like language". Extending C is 
>changing C, i.e. modifying the standard that defines C. 

I disagree with this, but I think I've expressed my opinion
often enough over the last few years, so we'll just have to
continue disagreeing.

-- Richard
-- 
Please remember to mention me / in tapes you leave behind.
0
Reply richard91 (3683) 11/19/2008 3:09:52 PM

On Nov 19, 4:44 am, Keith Thompson <ks...@mib.org> wrote:
> vipps...@gmail.com writes:
<snip>
> > Whatever POSIXLY_CORRECT is, it's defined in a standard other than C
> > (and for that matter, POSIX).
>
> I'm not sure that it's defined in any standard.  For purposes of this
> newsgroup, it suffices to say that it's not defined in the C standard
> (and nobody has suggested that it is).  The previous poster mentioned
> POSIXLY_CORRECT in passing in the context of talking about conforming
> or not conforming to standards.  (GNU software often doesn't quite
> conform to POSIX by default; setting POSIXLY_CORRECT causes it to
> conform more closely.)  It was a real-world example meant to
> illustrate a point.
>
> >                               C (and POSIX) says POSIXLY_CORRECT is an
> > identifier in the programmers namespace, which means he is under
> > complete control of what it is.
>
> POSIXLY_CORRECT in this context *is not an identifier*.  It's the name
> of an environment variable, which means it's a string whose address
> you could pass to getenv().  If you want to mention that it's
> off-topic, fine, but why go off on a tangent about how that particular
> character string could be used as an identifier in a C program?

Because I completely missed what Ertugrul said/illustrated with
POSIXCLY_CORRECT. I see it now that you pointed it out, thanks.
0
Reply vippstar (1211) 11/19/2008 6:02:41 PM

In article <20081118212552.14739638@ertes.de>,
Ertugrul SC6ylemez  <es@ertes.de> wrote:

>This is true and fine and great and everything, but I'm very
>disappointed by the responses, because all I got was being flamed off
>for using extensions, not a single comment on the actual subject.
>Nobody cared about the theoretical value in the (latter three) source
>codes.  It feels like nobody of the original responders even read the
>article -- where I pointed out that I used non-standard features! -- or
>bothered about understanding the code.

Your original subject is something I have some interest in, and my
initial impression was that you're going about it in entirely the wrong
way.
If I get the opportunity to do so before the article expires from my
newsserver (which may or may not happen), I intend to take a close
enough look at it to come up with something coherent and substantial to
say.  But that will take a bit longer than noticing and pointing out
that you're using ill-advised extensions that most of the world doesn't
have available would.


>By the way, people break standards all the time.  If standards limit you
>in what you can do for no apparent reason, they are bound to be broken,

....and if you're lucky, you will soon realize why the standard imposes
that restriction.  (If you're not lucky, you won't reach that
realization until you have a large mess of non-compliant stuff to deal
with.)

>with POSIX probably being the best example, or do you GNU users set
>POSIXLY_CORRECT?  I don't.

This (or equivalent mental discipline) is in fact recommended by most
of the people I know who regularly use GNU tools.  They've all been
bitten at one time or another by assuming GNU extensions where they
don't exist and can't be added.


dave

-- 
Dave Vandervies                                   dj3vande at eskimo dot com
>[P]rotect the originals with something that has sharp teeth, long tentacles
>and a big appetite.                        --Alexander Schreiber and Michel
In other words: Keep it with you.      Buijsman in the scary devil monastery
0
Reply dj3vande3 (264) 11/19/2008 6:13:41 PM

[Followup-To trimmed to comp.lang.c only]

In article <20081119014837.6018bf28@ertes.de>,
Ertugrul SC6ylemez  <es@ertes.de> wrote:
>vippstar@gmail.com wrote:

>> Because your message was off-topic. There's another possibility that
>> some cared, but chosen not to pollute this newsgroup with more off-
>> topic messages. Another reason to be on-topic.
>
>Being standards-compliant is one thing, simply being counter-innovative
>is another.

Your innovation is my users' heap of useless code.  The whole point of
standardization *is* to limit innovation in the interface, to
facilitate innovation at the next level up by giving users a consistent
platform to build on.

If you want to make a better compiler, that kind of innovation would be
welcomed by (many of the) people here, but it's not really appropriate
for discussion here; there are other places to talk about playing with
compilers and hacking on any particular compiler you want to start
with.
If you want to use (or implement) language features that C doesn't
have, then, well, you're not using C anymore, so it's kind of useless
to talk about it in comp.lang.c.

But if you want to do something new and interesting and implement it in
C, *that*'s (part of) what this newsgroup is here for.  Despite what
our resident trolls and whiners would have you believe, there's plenty
of room for innovation there, and most of that room is *created by* the
fact that we have a standard language to build on and don't have to
worry about whether I'm using the same compiler you are.

(If you want to discuss whether some extension to the language would be
useful, that's kind of a grey area; but it's more off-topic than
on-topic, and it's more likely to be tolerated when it's coming from
people who already have a history of making interesting contributions
that are unambiguously on-topic.)


>      Where should
>I post this instead?  In my opinion, this _is_ a C-related topic, at
>least because it shows something that is difficult to implement in
>standard C.

Building functional abstractions in C is a C-related topic and is
appropriate for discussion here.
Building functional abstractions in GCC's not-quite-C default language
is appropriate for discussion in places intended for discussion of
programming in GCC's not-quite-C default language.
Learning to recognize the difference is the first step on the path to
wisdom.


>By the way, according to your view, GCC and most other compilers are not
>C compilers.  They compile some language derived from C.

Adding "by default" in appropriate places would make that sentence
perfectly correct.
One of the few bits of compiler-specific information that's generally
considered acceptable here is how to make the compiler speak C and not
its own C-like dialect.  (For GCC it's '-ansi -pedantic' for C90, and
'-std=c99 -pedantic' for a partial C99 implementation.)


>> You've already been told this is off-topic. Please don't bring more
>> off-topic statements for fact-checking.
>
>You told me.  I'm unable to find any etiquette or posting rules.  This
>is a C-related topic.  The group name suggests it's on-topic.

For etiquette and posting rules,
<http://www.clc-wiki.net/wiki/C_community:comp.lang.c:Introduction>
is probably a good place to start.
(It may or may not be mentioned somewhere there, but a thick skin and a
willingness to learn are both pretty much essential.)


(It is rather unfortunate that most of the comments you got were on the
parts of your post that used GCC extensions; there's an interesting and
on-topic discussion hiding in the parts of your post that are
restricted to standard C.)


dave

-- 
Dave Vandervies                                   dj3vande at eskimo dot com
>[P]rotect the originals with something that has sharp teeth, long tentacles
>and a big appetite.                        --Alexander Schreiber and Michel
In other words: Keep it with you.      Buijsman in the scary devil monastery
0
Reply dj3vande3 (264) 11/19/2008 6:51:35 PM

vippstar wrote:
> Keith Thompson <ks...@mib.org> wrote:
>> vipps...@gmail.com writes:
>>> Keith Thompson <ks...@mib.org> wrote:
>>>> vipps...@gmail.com writes:
>>>>> Keith Thompson <ks...@mib.org> wrote:
>>>>>> vipps...@gmail.com writes:
>>>>>>> Keith Thompson <ks...@mib.org> wrote:
>>>>>>>> vipps...@gmail.com writes:
>>>>>>>>> Keith Thompson <ks...@mib.org> wrote:
>>>>>>>>>> vipps...@gmail.com writes:
>>>>>>>>>>> Keith Thompson <ks...@mib.org> wrote:
>>>>>>>>>>>> vipps...@gmail.com writes:
>>>>>>>>>>>>> Keith Thompson <ks...@mib.org> wrote:
>>>>>>>>>>>>>> vipps...@gmail.com writes:
>>>>>>>>>>>>>>> [blah blah blah blah blah]


Mental note: remember to *never* cross-post to comp.lang.c.


--AS
0
Reply asnarb (8) 11/19/2008 8:06:40 PM

In article <gg1n7n$pf6$1@rumours.uwaterloo.ca>,
 <dj3vande@csclub.uwaterloo.ca.invalid> wrote:

>Your innovation is my users' heap of useless code.  The whole point of
>standardization *is* to limit innovation in the interface, to
>facilitate innovation at the next level up by giving users a consistent
>platform to build on.

This is a false dichotomy.  Having unstandardised extensions doesn't
prevent you from coding to the standard.

>If you want to make a better compiler, that kind of innovation would be
>welcomed by (many of the) people here, but it's not really appropriate
>for discussion here; there are other places to talk about playing with
>compilers and hacking on any particular compiler you want to start
>with.

And this is another bogus argument.  If I want to discuss an extension
or change to C or C compilation, why on earth should I necessarily
want to do so in the context of some particular compiler?  I may not
even be a compiler hacker, and merely want to discuss it in the
abstract.

>If you want to use (or implement) language features that C doesn't
>have, then, well, you're not using C anymore, so it's kind of useless
>to talk about it in comp.lang.c.

Only if by "C" you mean exclusively "standardised C", which many of
us don't.

I encourage anyone with interesting ideas for C, that aren't
specific to some particular platform, to discuss them here.

-- Richard
-- 
Please remember to mention me / in tapes you leave behind.
0
Reply richard91 (3683) 11/19/2008 9:14:27 PM

dj3vande@csclub.uwaterloo.ca.invalid wrote:
> Ertugrul SC6ylemez  <es@ertes.de> wrote:
>> vippstar@gmail.com wrote:
>> 
>>> Because your message was off-topic. There's another possibility
>>> that some cared, but chosen not to pollute this newsgroup with
>>> more off-topic messages. Another reason to be on-topic.
>>
>> Being standards-compliant is one thing, simply being counter-
>> innovative is another.
> 
> Your innovation is my users' heap of useless code.  The whole
> point of standardization *is* to limit innovation in the
> interface, to facilitate innovation at the next level up by
> giving users a consistent platform to build on.
> 
> If you want to make a better compiler, that kind of innovation
> would be welcomed by (many of the) people here, but it's not
> really appropriate for discussion here; there are other places
> to talk about playing with compilers and hacking on any
> particular compiler you want to start with.
>
> If you want to use (or implement) language features that C
> doesn't have, then, well, you're not using C anymore, so it's
> kind of useless to talk about it in comp.lang.c.
> 
> But if you want to do something new and interesting and
> implement it in C, *that*'s (part of) what this newsgroup is
> here for.  Despite what our resident trolls and whiners would
> have you believe, there's plenty of room for innovation there,
> and most of that room is *created by* the fact that we have a
> standard language to build on and don't have to worry about
> whether I'm using the same compiler you are.

This is just about the best description I have seen of c.l.c
topicality.  Note, in your last paragraph, that the 'new and
interesting' part can be thoroughly described by publishing its
code, written in standard C.

-- 
 [mail]: Chuck F (cbfalconer at maineline dot net) 
 [page]: <http://cbfalconer.home.att.net>
            Try the download section.
0
Reply cbfalconer (19183) 11/20/2008 12:55:17 AM

vippstar@gmail.com writes:

> Spam: off-topic message luring views.
> Your post: interesting off-topic discussion seeking different POVs.
> At worst: spam.

You're quite mistaken as to what spam is.

-- 
Aatu Koskensilta (aatu.koskensilta@uta.fi)

"Wovon man nicht sprechen kann, darüber muss man schweigen"
 - Ludwig Wittgenstein, Tractatus Logico-Philosophicus
0
Reply aatu.koskensilta1 (232) 11/20/2008 1:19:00 AM

Ertugrul Söylemez <es@ertes.de> writes:

> By the way, the idea was inspired by The Evolution of a Haskell
> Programmer [1].  I thought, it would be funny to try to implement some
> of those examples in C.  Unfortunately C's type system is not
> Turing-complete.

Neither is Haskell's.

-- 
Aatu Koskensilta (aatu.koskensilta@uta.fi)

"Wovon man nicht sprechen kann, darüber muss man schweigen"
 - Ludwig Wittgenstein, Tractatus Logico-Philosophicus
0
Reply aatu.koskensilta1 (232) 11/20/2008 1:20:59 AM

Aatu Koskensilta <aatu.koskensilta@uta.fi> wrote:

> Ertugrul S=C3=B6ylemez <es@ertes.de> writes:
>
> > By the way, the idea was inspired by The Evolution of a Haskell
> > Programmer [1].  I thought, it would be funny to try to implement
> > some of those examples in C.  Unfortunately C's type system is not
> > Turing-complete.
>
> Neither is Haskell's.

Haskell's type system gives me the same computational power as Haskell
itself.  Maybe I missed something?


Greets,
Ertugrul.


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)

0
Reply es1 (159) 11/20/2008 3:19:37 AM

Ertugrul Söylemez <es@ertes.de> writes:

> Haskell's type system gives me the same computational power as Haskell
> itself.  Maybe I missed something?

Yes. You're missing the fact that Haskell's type system, as defined by
the Haskell report, does not give you the same computational power as
Haskell itself.

-- 
Aatu Koskensilta (aatu.koskensilta@uta.fi)

"Wovon man nicht sprechen kann, darüber muss man schweigen"
 - Ludwig Wittgenstein, Tractatus Logico-Philosophicus
0
Reply aatu.koskensilta1 (232) 11/20/2008 1:17:44 PM

richard@cogsci.ed.ac.uk (Richard Tobin) wrote:

> In article <gg1n7n$pf6$1@rumours.uwaterloo.ca>,
>  <dj3vande@csclub.uwaterloo.ca.invalid> wrote:
>
> > If you want to make a better compiler, that kind of innovation would
> > be welcomed by (many of the) people here, but it's not really
> > appropriate for discussion here; there are other places to talk
> > about playing with compilers and hacking on any particular compiler
> > you want to start with.
>
> And this is another bogus argument.  If I want to discuss an extension
> or change to C or C compilation, why on earth should I necessarily
> want to do so in the context of some particular compiler?  I may not
> even be a compiler hacker, and merely want to discuss it in the
> abstract.

Well, some people think, I wanted to discuss an extension.  That was by
no means my intention.  I picked up a classic language and tried to take
it to its limits by trying to incorporate functional concepts into it.
That was the experiment.

My conclusion is that without extensions, C is not flexible enough to do
this.  Of course, C is a Turing-complete general purpose language, so
there is in theory nothing you couldn't do in C.  I showed that this
property is not a feature, but instead simply natural for every general
purpose language.  I showed that things, which are very easy to do in
other languages (including imperative languages like Python), is a PITA
to do in C, and this is not related to better library support in other
languages or to the fact that you need to do memory management yourself.
It's really related to the nature of the C language itself.


> I encourage anyone with interesting ideas for C, that aren't specific
> to some particular platform, to discuss them here.

Yes, I agree here, but I like to note that I never proposed additions or
changes to C.


Greets,
Ertugrul.


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)

0
Reply es1 (159) 11/20/2008 10:03:23 PM

In article <gg1vjj$6bo$3@pc-news.cogsci.ed.ac.uk>,
Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
>In article <gg1n7n$pf6$1@rumours.uwaterloo.ca>,
> <dj3vande@csclub.uwaterloo.ca.invalid> wrote:
>
>>Your innovation is my users' heap of useless code.  The whole point of
>>standardization *is* to limit innovation in the interface, to
>>facilitate innovation at the next level up by giving users a consistent
>>platform to build on.
>
>This is a false dichotomy.  Having unstandardised extensions doesn't
>prevent you from coding to the standard.

And how, exactly, does that help me when somebody presents a
potentially-interesting idea expressed using extensions I don't have?


>>If you want to make a better compiler, that kind of innovation would be
>>welcomed by (many of the) people here, but it's not really appropriate
>>for discussion here; there are other places to talk about playing with
>>compilers and hacking on any particular compiler you want to start
>>with.
>
>And this is another bogus argument.  If I want to discuss an extension
>or change to C or C compilation, why on earth should I necessarily
>want to do so in the context of some particular compiler?

If you'd read my entire post, you would have noticed that I addressed
exactly that point a few lines down; and had you spent a few
milliseconds thinking about it, instead of just trying to play chatbot
with it, that should have enough of a clue to realize that the part
you're replying to wasn't intended to address that particular case at
all.


>>If you want to use (or implement) language features that C doesn't
>>have, then, well, you're not using C anymore, so it's kind of useless
>>to talk about it in comp.lang.c.
>
>Only if by "C" you mean exclusively "standardised C", which many of
>us don't.

So how would *you* define C, then?  "Anything my compiler compiles"?
Not very useful to the rest of us.  "Anything anybody's compiler
compiles"?  Not very useful to *anybody*.  Some subset of that?  Where
do you draw the line?  (Oh, Look!  Some international group that
specializes in defining things has published a definition of some
programming language called "C"!  Why don't we use that?  That way we
know we're all talking about the same thing!)


dave

-- 
Dave Vandervies                                     dj3vande at eskimo dot com
Other than that, your abstract needs to be completely rewritten.  Fortunately,
that's something that can be left until the rest of your document has been
completely rewritten.                            --Simon G Best in comp.theory
0
Reply dj3vande3 (264) 11/21/2008 4:58:27 AM

Aatu Koskensilta wrote:
> Ertugrul Söylemez <es@ertes.de> writes:
>> Haskell's type system gives me the same computational power as Haskell
>> itself.  Maybe I missed something?
> 
> Yes. You're missing the fact that Haskell's type system, as defined by
> the Haskell report, does not give you the same computational power as
> Haskell itself.

I think you mean Haskell 98 and he doesn't. Regardless, Haskell 98 is almost
entirely unused today (GHC's extended Haskell is the defacto standard).

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u
0
Reply jon (3267) 11/23/2008 10:23:33 PM

Jon Harrop <jon@ffconsultancy.com> writes:

> Aatu Koskensilta wrote:
> 
> > Yes. You're missing the fact that Haskell's type system, as defined by
> > the Haskell report, does not give you the same computational power as
> > Haskell itself.
> 
> I think you mean Haskell 98 and he doesn't. Regardless, Haskell 98 is almost
> entirely unused today (GHC's extended Haskell is the defacto standard).

Right. Multi-parameter type classes and functional dependencies in
particular allow us to perform arbitrary computations on the type
level. Such magic has its charm, though the charm is alas not entirely
unlike that of advanced C++ template magic.

We must not lose sight of the fact this discussion is cross-posted in
comp.lang.c, where all discussion absolutely must be limited to what
is standard conforming. Non-standard extensions of Haskell are thus
obviously even more off-topic than standard Haskell.

Also, when setting follow-ups, its a matter of courtesy to include a
note of that in the body of the post.

In closing, just to please the C crowd:

 void main()

-- 
Aatu Koskensilta (aatu.koskensilta@uta.fi)

"Wovon man nicht sprechen kann, darüber muss man schweigen"
 - Ludwig Wittgenstein, Tractatus Logico-Philosophicus
0
Reply aatu.koskensilta1 (232) 11/24/2008 1:53:39 PM

Ertugrul S�ylemez <es@ertes.de> writes:
> [1] http://blog.ertes.de/2008/11/obscure-c-from-new-perspective.html

I hereby nomninate you for membership in "evil geniuses for a better
tomorrow". ;-)
0
Reply phr.cx (5483) 2/5/2009 10:58:44 AM

Paul Rubin <http://phr.cx@NOSPAM.invalid> wrote:

> > [1] http://blog.ertes.de/2008/11/obscure-c-from-new-perspective.html
>
> I hereby nomninate you for membership in "evil geniuses for a better
> tomorrow". ;-)

Oh hehe, I almost forgot that piece of code.  It's not that evil.  I'm
just abusing a highly imperative language for highly functional
stuff. ;)

BTW, I'll refrain from calling that language "C" again, but rather call
it "a C-like language".  The last time I made the mistake to call it "C"
got me flamed off in comp.lang.c. =)


Greets,
Ertugrul.


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/5/2009 1:48:00 PM

Ertugrul =?UTF-8?B?U8O2eWxlbWV6?= <es@ertes.de> writes:
>I thought it would be funny to try to bring functional
>concepts into the C language. 

  To me, a lack of automatic memory management makes
  functional programming difficult in C.

  How does one usually deal with the following problem?

  A function returns a value that is passed to another
  function, say

print( read() )

  . Now, one would like to see it this way that the value
  is created by �read� and consumed by �print�.

  When the size and structure of the value is dynamic, �read�
  will allocate parts of the value.

  So, when �print� is �consuming� the value, it seems
  natural for �print� to call �free� on this value later.

  But there, the problems start:

      - When parts of the argument structure are shared,
        they possibly should not be freed.

      - A client of �print� might pass in objects with 
        static or automatic storage duration, which 
        should not be freed at all.

  One might work out a set of rules to deal with all this,
  but I believe programming is much more complicate this way.

  I believe some people have a concept of �ownership� of
  objects with allocated storage duration that might be
  passed or not be passed with those objects. But we do not
  have common guidelines in C for this ownership transfer?

  In the end, one might invest more time in thinking about
  memory management than about the actual programming problem.

  So, I believe, this is the real problem, when one tries
  to do functional programming in C.

0
Reply ram (2827) 1/25/2010 10:14:14 PM

ram@zedat.fu-berlin.de (Stefan Ram) writes:
>   A function returns a value that is passed to another
>   function, say
>
> print( read() )

I once wrote an embedded lisp interpreter where you'd write
something like

  Lisp_value f() {
    mark();
    ...
    print (wrap (read()));
    ...
    release ();
  }

Basically the interpreter had a stack of values protected from garbage
collection.  wrap(...) would push a value onto the stack and return the
same value.  mark() would save a "frame pointer" and push the old frame
pointer onto the stack, and release() would pop back to the saved frame
pointer.  Throwing an exception would pop the stack back to the frame
pointer saved by the exception handler.  So that temporary value
returned by read() would be protected through the dynamic context of
f(), and of course saving any further references would make it reachable
by gc.  This really wasn't too bad.  If you wanted to use read/print in
a loop you could put the value in a mutable cell in order to avoid
unwanted stack growth, something like:

    Lisp_value x = Nil;
    wrap_ref(&x);
    for (...) {
       x = read();
       print (x);
    }

>       - When parts of the argument structure are shared,
>         they possibly should not be freed.
>
>       - A client of »print« might pass in objects with 
>         static or automatic storage duration, which 
>         should not be freed at all.

Well sure, but such sharing would be discovered by a tracing gc.

>   In the end, one might invest more time in thinking about
>   memory management than about the actual programming problem.

Maybe for a high performance system.  The simple-minded thing that I did
was fairly easy to use and worked reliably, though I guess it
may have had some efficiency shortcomings, and couldn't have handled
an evaluation model that allowed (e.g.) saved continuations.
0
Reply no.email6 (1518) 1/25/2010 10:36:53 PM

Paul Rubin <no.email@nospam.invalid> writes:
>Well sure, but such sharing would be discovered by a tracing gc.

  Yes, the whole point of my post is that C usually does
  /not have/ a GC. So I infer that functional programming,
  therefore, is difficult or nearly impossible (beyond a
  certain level of complexity) in C.

0
Reply ram (2827) 1/25/2010 10:55:05 PM

Stefan Ram a �crit :
> Ertugrul =?UTF-8?B?U8O2eWxlbWV6?= <es@ertes.de> writes:
>> I thought it would be funny to try to bring functional
>> concepts into the C language. 
> 
>   To me, a lack of automatic memory management makes
>   functional programming difficult in C.
> 

snip...
> 
>   In the end, one might invest more time in thinking about
>   memory management than about the actual programming problem.
> 
>   So, I believe, this is the real problem, when one tries
>   to do functional programming in C.
> 

It depends what "C" you are using.

lcc-win proposes a garbage collector in its standard distribution.
All the problems above are solved with a gc
0
Reply jacob24 (973) 1/25/2010 11:05:13 PM

Stefan Ram a �crit :
> Paul Rubin <no.email@nospam.invalid> writes:
>> Well sure, but such sharing would be discovered by a tracing gc.
> 
>   Yes, the whole point of my post is that C usually does
>   /not have/ a GC. So I infer that functional programming,
>   therefore, is difficult or nearly impossible (beyond a
>   certain level of complexity) in C.
> 

I have been proposing a garbage collector forC since 2004. The
garbage collector is a part of thestandard lcc-win distribution.

The same collector is available for most workstation environments.

jacob
0
Reply jacob24 (973) 1/25/2010 11:08:19 PM

jacob navia <jacob@nospam.org> writes:
>It depends what "C" you are using.

  I thought about something along the lines of 
  ISO/IEC 9899:1999 (E).

0
Reply ram (2827) 1/25/2010 11:12:51 PM

Stefan Ram a �crit :
> jacob navia <jacob@nospam.org> writes:
>> It depends what "C" you are using.
> 
>   I thought about something along the lines of 
>   ISO/IEC 9899:1999 (E).
> 
The gc is a library, like a graphics library or a network library.

Are you implying that you can't do network programming in C because "network" doesn't appear in the 
standard?

The standard doesn't speak a word about graphics either. You can't do graphics in C then?

Your viewpoint of limiting C to what is explicitly said in the standard is just another way of the old:

"You can't do anything serious in C"

and then (implicitly)

"Use C++" or whatever
0
Reply jacob24 (973) 1/25/2010 11:21:53 PM

On 25 jan, 23:55, r...@zedat.fu-berlin.de (Stefan Ram) wrote:
> Paul Rubin <no.em...@nospam.invalid> writes:
> >Well sure, but such sharing would be discovered by a tracing gc.
>
> =A0 Yes, the whole point of my post is that C usually does
> =A0 /not have/ a GC. So I infer that functional programming,
> =A0 therefore, is difficult or nearly impossible (beyond a
> =A0 certain level of complexity) in C.

I have already answered to this kind of question recently. You don't
need a GC, just a richer set of ownership rules. In the C Object
System (100% C lib) I use new, delete and autoDelete (delayed delete)
for object creation/destruction and retain, release and autoRelease
(delayed release) for object ownership. The reason why there is a
difference between creation and ownership comes from the possibility
to convert a posteriori an existing code back and forth to something
semi-gc where all new do an autoDelete and no delete are required from
the user (and obviously the rule does not apply to retain/release life-
cycle). Since I have adopted these rules with _local_ balance (new <->
delete/autoDelete, retain <-> release/autoRelease), I don't have
anymore memory leaks.

Once you have ownership, you need few more concepts to be able to
program in C as you would in Lisp (and beyond). Another (big) step is
the implementation of generic closures (high order functions and high
order messages) and there you need the full expressive power of COS...

cheers,

ld.
0
Reply Laurent.Deniau (124) 1/25/2010 11:22:58 PM

jacob navia <jacob@nospam.org> writes:
>Are you implying that you can't do network programming in C
>because "network" doesn't appear in the standard?

  Given only an implementation of ISO/IEC 9899:1999 (E),
  you can not do this. I wrote something about this with C++
  in mind, but it applies to C as well:

http://www.purl.org/stefan_ram/pub/c++_standard_extensions_en

>"Use C++" or whatever

  The problems apply to C++ as well, but not to Java, because
  Java has a GC and a network library /in its standard J2EE/.

0
Reply ram (2827) 1/25/2010 11:31:07 PM

ld <laurent.deniau@gmail.com> writes:
>I have already answered to this kind of question recently.
>You don't need a GC, just a richer set of ownership rules.

  Yes, please give me the URI of this set!

0
Reply ram (2827) 1/25/2010 11:33:25 PM

jacob navia <jacob@nospam.org> writes:
[...]
> Your viewpoint of limiting C to what is explicitly said in the
> standard is just another way of the old:
>
> "You can't do anything serious in C"
>
> and then (implicitly)
>
> "Use C++" or whatever

You wouldn't be waging a campaign against C99, would you?

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 1/25/2010 11:36:23 PM

On 26 jan, 00:33, r...@zedat.fu-berlin.de (Stefan Ram) wrote:
> ld <laurent.den...@gmail.com> writes:
> >I have already answered to this kind of question recently.
> >You don't need a GC, just a richer set of ownership rules.
>
> =A0 Yes, please give me the URI of this set!

I mentioned the list of messages in my post. You can find the semantic
explanation in the paper

http://cos.cvs.sourceforge.net/viewvc/cos/doc/cos-draft-dls09.pdf

or in the slides

http://cos.cvs.sourceforge.net/viewvc/cos/doc/slides-cos.pdf

You can also read the doc on ownership and memory management from the
Apple dev center since they use autoRelease pools for more than a
decade in Cocoa (and still nowadays despite of the introduction of the
GC with Objective-C 2.0).

The code can be browsed on the cvs repository (things in CosBase are
stable but on CosStd and CosExt are unstable).

cheers,

ld.

0
Reply Laurent.Deniau (124) 1/25/2010 11:44:01 PM

ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>Well sure, but such sharing would be discovered by a tracing gc.
>
>   Yes, the whole point of my post is that C usually does
>   /not have/ a GC. So I infer that functional programming,
>   therefore, is difficult or nearly impossible (beyond a
>   certain level of complexity) in C.

The functional programming would only work on a certain class of objects
within the C program, that are collected by an internal gc.  Sometimes
what this leads to is called "Greenspun's Tenth Law" ;-).  

There are also so-called conservative gc's for C and C++ (that treat all
data words as possible heap pointers) but at least as a matter of
principle, those can be considered unsatisfying.

Anyway I came late into this thread, but I don't think anyone was
proposing to embed Haskell as cpp macros or anything like that ;-).  The
idea is just that it's possible for one's C programs to be influenced by
functional style, and to implement some nontrivial functional constructs
through a few coding disciplines supported by some utility functions.
0
Reply no.email6 (1518) 1/26/2010 3:04:34 AM

ld <laurent.deniau@gmail.com> writes:
>>>You don't need a GC, just a richer set of ownership rules.
>>Yes, please give me the URI of this set!
>http://cos.cvs.sourceforge.net/viewvc/cos/doc/cos-draft-dls09.pdf

  This seems to be a library that either uses garbage collection
  or user aided reference counting.

  I was hoping for ownership rules for plain C objects or
  linked C data structures.

  C does not have a garbage collector.

  A reference counter is an additional subobject that must be
  added to all objects to be managed in this way. 

  This URI list rules for reference counting with COM (using
  "AddRef" and "Release"):

http://en.wikipedia.org/wiki/Component_Object_Model#Reference_counting

  And this URI lists some of the problems with reference counting:

http://en.wikipedia.org/wiki/Component_Object_Model#Reference_counting_2

  Another URI:

      "Bugs caused by incorrect reference counting in COM
      systems are notoriously hard to resolve"

http://en.wikipedia.org/wiki/Reference_counting#COM

  I believe having read that problems with reference counting
  are a reason, why COM does not get so much support from
  Microsoft anymore, while many major Windows applications
  still use COM. I can not find a direct source for this,
  but the following goes into this direction:

      �The messiness of COM (Component Object Model) is
      removed. (...) .NET addresses many of the shortfalls of
      COM, including (...) reference counting (...)�

      �The developer controls the lifetime of a COM object.
      AddRef and Release live in infamy. They are methods of
      the IUnknown interface and control the persistence of
      the COM object. If implemented incorrectly, a COM object
      could be released prematurely or, conversely, never be
      released and be the source of memory leaks. The .NET
      memory manager, appropriately named the Garbage
      Collector, is responsible for managing component
      lifetimes for the application - no more AddRef and Release.�

http://www.codeguru.com/csharp/sample_chapter/article.php/c8245/

0
Reply ram (2827) 1/26/2010 3:47:47 AM

"Paul Rubin" <no.email@nospam.invalid> wrote in message 
news:7x7hr5va65.fsf@ruckus.brouhaha.com...
> ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>>Well sure, but such sharing would be discovered by a tracing gc.
>>
>>   Yes, the whole point of my post is that C usually does
>>   /not have/ a GC. So I infer that functional programming,
>>   therefore, is difficult or nearly impossible (beyond a
>>   certain level of complexity) in C.
>
> The functional programming would only work on a certain class of objects
> within the C program, that are collected by an internal gc.  Sometimes
> what this leads to is called "Greenspun's Tenth Law" ;-).
>
> There are also so-called conservative gc's for C and C++ (that treat all
> data words as possible heap pointers) but at least as a matter of
> principle, those can be considered unsatisfying.
>

yeah.
they can tend to be slow and unreliable, and can be rather ill-behaved for 
certain usage patterns...

ideally, it would be preferable to avoid a conservative GC (and instead use 
precise GC), but alas, for C, this leads to far too much hassle/overhead 
(having to mess with registering and unregistering roots, ...).

the JVM seem to use an alternate strategy for JNI:
references are "local" or "global", where local references have a 
constrained lifespan (and may be destroyed after the JNI method returns).


for C, I have ended up developing a sort of pseudo-GC strategy (used mostly 
in my compiler internals), where the allocator just sort of naively 
allocates from sliding buffers, which may be destroyed/reused when done.

any data to preserved then is, manually, copied elsewhere (although, more 
often, it is just discarded, with the result having been "transcribed" into 
a different form).
if made automatic, I guess this would be a sort of crude copy-collector.

OTOH, this could be made into a "semi-automatic" API, whereby one could 
instruct the system to copy the data, but it goes about the actual logistics 
of doing so (likely with the help of user-registered "copy" handlers). (in 
the "manual" strategy, usually type-specific data-copying functions are 
written for any data needing to be copied...).

but, anyways, the main advantage of this strategy is that it does well for 
the usage patterns which seem to pop up in my compiler: producing large 
volumes of objects in short bursts, which almost all turn into garbage.

this particular usage-cases tend to kill my main GC (which tends to work 
best with a gradual accumulation of garbage at a relatively low rate).


> Anyway I came late into this thread, but I don't think anyone was
> proposing to embed Haskell as cpp macros or anything like that ;-).  The
> idea is just that it's possible for one's C programs to be influenced by
> functional style, and to implement some nontrivial functional constructs
> through a few coding disciplines supported by some utility functions.

yeah.
Haskell mixed in with C would be nasty...

well, of note:
I do have support for a "closure" facility in my case (via an API call).

however, I haven't really exactly used it much (except in a few edge cases 
where it was needed), and generally it would require manually "capturing" 
the bindings in the form of a heap-allocated struct (or similar).

so, in general, it has neither the grace nor the elegance of the FP 
analogue.

it tends to be actually more usable just to pass an object with the funtion 
embedded in a function pointer (even though) you can't simply call this as 
if it were a function pointer. this tends actually to be a lot more 
convinient, as well as being faster (via lack of crufty "transfer thunks") 
and typically generating less garbage...



0
Reply cr88192355 (1754) 1/26/2010 4:25:54 AM

Stefan Ram a �crit :
> 
>   C does not have a garbage collector.
> 

Many things are left for system libraries, like graphics, network,
garbage collectors, and many other things like (for instance)
directory access, thread management, multiprocessing etc.

All of this can be done in C if you do not arbitrarily restrict
the language to the minimal subset as you are trying to do here.

I have promoted and distributed a garbage collector for C since
several years. People like you (and the other "regs") have always
fought this, so your attitude is not surprising.

What is surprising is that now you refuse even to acknowledge that
a widely distributed implementation of gc exists, and it is used.

Your argument that "it is not part of the text of the standard"
is just ridiculous. The "C" of the standard is not even able to
use a directory effectively and there is NO serious software in C
that uses that  minimal subset.

With your attitude there is no software written in C.

0
Reply jacob24 (973) 1/26/2010 6:26:49 AM

Stefan Ram a �crit :
> 
> http://en.wikipedia.org/wiki/Reference_counting#COM
> 
>   I believe having read that problems with reference counting
>   are a reason, why COM does not get so much support from
>   Microsoft anymore, while many major Windows applications
>   still use COM. I can not find a direct source for this,
>   but the following goes into this direction:
> 
>       �The messiness of COM (Component Object Model) is
>       removed. (...) .NET addresses many of the shortfalls of
>       COM, including (...) reference counting (...)�
> 
>       �The developer controls the lifetime of a COM object.
>       AddRef and Release live in infamy. They are methods of
>       the IUnknown interface and control the persistence of
>       the COM object. If implemented incorrectly, a COM object
>       could be released prematurely or, conversely, never be
>       released and be the source of memory leaks. The .NET
>       memory manager, appropriately named the Garbage
>       Collector, is responsible for managing component
>       lifetimes for the application - no more AddRef and Release.�
> 
> http://www.codeguru.com/csharp/sample_chapter/article.php/c8245/
> 

That is why lcc-win proposes a garbage collector, because is the only
sensible solution.

Obviously your agenda is just to demonstrate that C is unable to do
anything. Granted. Go ahead. But you aren't confusing anyone.
0
Reply jacob31 (869) 1/26/2010 6:37:29 AM

On Jan 26, 6:37=A0am, jacob navia <ja...@spamsink.net> wrote:
>
> That is why lcc-win proposes a garbage collector, because is the only
> sensible solution.

And what language do you write your garbage collector in? ;)

Garbage collectors clearly have their place, and an (optional) one
would be a boon to any language that doesn't have one built in.  But
there are perfectly good alternatives, besides manual reference
counting.  The fact that COM screwed up reference counting, doesn't
mean that reference counting is a non-starter.  In many circumstances
a smart pointer is preferable to GC, as it gives a programmer greater
control over deterministic destruction (RAII works a lot better on
managing mutexes than GC, for example -- lock()/unlock() cares about
timing in a way malloc()/free() doesn't). In many circumstance, GC is
preferable to smart pointers, as the programmer doesn't care about
those things.

As ever: There is no silver bullet.
0
Reply gwowen (518) 1/26/2010 7:52:44 AM

gwowen a �crit :
> On Jan 26, 6:37 am, jacob navia <ja...@spamsink.net> wrote:
>> That is why lcc-win proposes a garbage collector, because is the only
>> sensible solution.
> 
> And what language do you write your garbage collector in? ;)
>

Boehm's GC is written in plain C. Yes, you can write a GC in C. There
are a few bits and pieces done in assembly, but for the most part
everything is in C.

> Garbage collectors clearly have their place, and an (optional) one
> would be a boon to any language that doesn't have one built in.  

True

> But
> there are perfectly good alternatives, besides manual reference
> counting.  The fact that COM screwed up reference counting, doesn't
> mean that reference counting is a non-starter.  

COM did not "screw it". Reference counting has its drawbacks, that's all.

> In many circumstances
> a smart pointer is preferable to GC, as it gives a programmer greater
> control over deterministic destruction (RAII works a lot better on
> managing mutexes than GC, for example -- lock()/unlock() cares about
> timing in a way malloc()/free() doesn't). 

That could be done in C if we had operator overloading, something I have
been trying to promote for years.

> In many circumstance, GC is
> preferable to smart pointers, as the programmer doesn't care about
> those things.
> 

Yes.
> As ever: There is no silver bullet.

True. GC has its drawbacks too. For instance if you forget a reference to some
huge object you create an enormous memory leak since the collector can't
free it. Finding out where is that reference can be an incredibly complex
task.

Note that that is a problem for ALL GC's, java, lisp whatever.
0
Reply jacob24 (973) 1/26/2010 8:04:47 AM

On 26 Jan, 08:04, jacob navia <ja...@nospam.org> wrote:
> gwowen a =E9crit :

<snip>

> > As ever: There is no silver bullet.
>
> True. GC has its drawbacks too. For instance if you forget a reference to=
 some
> huge object you create an enormous memory leak since the collector can't
> free it. Finding out where is that reference can be an incredibly complex
> task.
>
> Note that that is a problem for ALL GC's, java, lisp whatever.

it has to be, otherwise the garbage collector would have to read your
mind. "ah, I see he has a reference to GiganticDataStructure that he
meant to get rid of. I'll just null it out and re-run gc".
0
Reply nick_keighley_nospam (4574) 1/26/2010 8:18:07 AM

On Jan 26, 8:04=A0am, jacob navia <ja...@nospam.org> wrote:
> > But
> > there are perfectly good alternatives, besides manual reference
> > counting. =A0The fact that COM screwed up reference counting, doesn't
> > mean that reference counting is a non-starter. =A0
>
> COM did not "screw it". Reference counting has its drawbacks, that's all.

The IUnknown AddRef() and Release() interface is incredibly brittle
and error prone.  Making a programmer manage all the references by
hand is a bad idea.  AddRef/Release is to reference counting as malloc
()/free() is to memory.  It's not consistent to repeatedly recommend
GC for memory, without spotting that the IUnknown is prone to the same
problem.

As the background mechanism, reference counting is fine -- just like
heap allocation is fine.  It is forcing the programmer to manage it by
hand that can frequently lead to errors.  It's actually probably worse
for interfaces, because most programmers have an idea who the "owner"
of some memory is, which, in my experience, is not necessarily the
case with Interfaces.  Also, leaked memory is easily cleaned up at
process exit time -- that's also not necessarily the case for non-
memory resources.
0
Reply gwowen (518) 1/26/2010 9:32:06 AM

On Tue, 26 Jan 2010 07:26:49 +0100
jacob navia <jacob@nospam.org> wrote:

> Your argument that "it is not part of the text of the standard"
> is just ridiculous. The "C" of the standard is not even able to
> use a directory effectively and there is NO serious software in C
> that uses that  minimal subset.

You've heard of Lua, yeah?  http://www.lua.org/  It's a very serious
piece of software; one of the fastest scripting languages around.  And
written entirely in ANSI C with only a handful of concessions (such as
dlopen to allow for extensions).

It's quite easy to write great, reusable, reliable software components
in ANSI C without reaching for OS-specific extensions.

B.
0
Reply nntp550 (4244) 1/26/2010 9:47:54 AM

On Jan 26, 10:04=A0am, jacob navia <ja...@nospam.org> wrote:
> gwowen a =E9crit :
>
> > On Jan 26, 6:37 am, jacob navia <ja...@spamsink.net> wrote:
> >> That is why lcc-win proposes a garbage collector, because is the only
> >> sensible solution.
>
> > And what language do you write your garbage collector in? ;)
>
> Boehm's GC is written in plain C. Yes, you can write a GC in C. There
> are a few bits and pieces done in assembly, but for the most part
> everything is in C.
>
> > Garbage collectors clearly have their place, and an (optional) one
> > would be a boon to any language that doesn't have one built in. =A0
>
> True
>
> > But
> > there are perfectly good alternatives, besides manual reference
> > counting. =A0The fact that COM screwed up reference counting, doesn't
> > mean that reference counting is a non-starter. =A0
>
> COM did not "screw it". Reference counting has its drawbacks, that's all.

It's not in any way convenient for the programmer. The fact that all
parties involved have to consistently count references is as error
prone as simply enforcing the proper use of malloc() & free() and
equivalents, and it has led to notoriously hard to find bugs. Even
Microsoft admitted that COM did, in fact, "screw it" which is why they
favoured tracing GC in .NET, so there's no point in trying to defend
its shortcomings. My personal belief is that *manual* reference
counting is still a bad idea - why do it when you can completely
decouple it from the programmer by providing him with a decent memory
manager? That way, everybody wins. And if you can't do that, just let
the poor guy manage malloc() & free(), why burden him/her with a
crippled interface?

> > In many circumstances
> > a smart pointer is preferable to GC, as it gives a programmer greater
> > control over deterministic destruction (RAII works a lot better on
> > managing mutexes than GC, for example -- lock()/unlock() cares about
> > timing in a way malloc()/free() doesn't).
>
> That could be done in C if we had operator overloading, something I have
> been trying to promote for years.

Operator overloading and lots of preprocessor tricks, correct?

> > As ever: There is no silver bullet.
>
> True. GC has its drawbacks too. For instance if you forget a reference to=
 some
> huge object you create an enormous memory leak since the collector can't
> free it. Finding out where is that reference can be an incredibly complex
> task.

This can be a problem with smart pointers as well. Typical example:
shared_ptr between an automatic pointer and a member of a singleton
(seen it a thousand times..).
0
Reply electricdelta (73) 1/26/2010 10:09:43 AM

Rob Kendrick a �crit :
> On Tue, 26 Jan 2010 07:26:49 +0100
> jacob navia <jacob@nospam.org> wrote:
> 
>> Your argument that "it is not part of the text of the standard"
>> is just ridiculous. The "C" of the standard is not even able to
>> use a directory effectively and there is NO serious software in C
>> that uses that  minimal subset.
> 
> You've heard of Lua, yeah?  http://www.lua.org/  It's a very serious
> piece of software; one of the fastest scripting languages around.  And
> written entirely in ANSI C with only a handful of concessions (such as
> dlopen to allow for extensions).
> 
Sure, then graphics, network, and whatever are done by loading

AN EXTERNAL LIBRARY

That is the same as with C. You link in C statically (or dynamically)
but you can't do any network/graphics/dynamic loading/you-name-it
without having to use external libraries what was my point!


> It's quite easy to write great, reusable, reliable software components
> in ANSI C without reaching for OS-specific extensions.
> 
> B.

Of course. Then you use dlopen to load all the OS-specific components!
You have just confirmed what I said:

Using ONLY the minimum mentioned in the standard you can't use directories
graphics, network and many other things that are essential today.

The standard is just a common minimum and a program that uses standard
libraries is written in C and uses extensions like (for instance) a GC.
0
Reply jacob24 (973) 1/26/2010 10:13:28 AM

In article <hjm2j9$52l$1@speranza.aioe.org>,
jacob navia  <jacob@jspamsink.org> wrote:

>That is why lcc-win proposes a garbage collector, because is the only
>sensible solution.

Is your garbage collector adequate for heavily recursive
functional-style programming?  You probably also need good
tail-recursion optimisation.  TRO may help garbage collection
if it removes stack frames that would otherwise "hold on" to
garbage.

-- Richard
-- 
Please remember to mention me / in tapes you leave behind.
0
Reply richard91 (3683) 1/26/2010 10:35:57 AM

jacob navia wrote:
> Stefan Ram a �crit :
>>
>>   C does not have a garbage collector.
>>
> 
> Many things are left for system libraries, like graphics, network,
> garbage collectors, and many other things like (for instance)
> directory access, thread management, multiprocessing etc.

Right.

> All of this can be done in C if you do not arbitrarily restrict
> the language to the minimal subset as you are trying to do here.

Sure. Nevertheless, if one does not restrict oneself in that way, one 
gives up a certain degree of portability - the fewer restrictions one 
places on what third-party features one accepts, the less portable one's 
code. It seems that you don't place a high value on portability, since 
you've basically selected one platform (possibly two) and stuck to it 
(them). Not everybody has that freedom.

> I have promoted and distributed a garbage collector for C since
> several years. People like you (and the other "regs") have always
> fought this, so your attitude is not surprising.

Nobody has fought your distribution of a GC. It is true that people in 
this newsgroup have objected to your using it as a dumping ground for 
advertisements. But if you were to promote it in appropriate channels, 
e.g. your web site, nobody could reasonably object to that.

> What is surprising is that now you refuse even to acknowledge that
> a widely distributed implementation of gc exists, and it is used.

He isn't refusing to acknowledge that garbage collectors exist. He's 
arguing that C doesn't have one. It doesn't. *You* have one. Your 
implementation may well provide one, as an extension. But C itself does 
not have one.

> Your argument that "it is not part of the text of the standard"
> is just ridiculous.

No, it's a rational stance.

 > The "C" of the standard is not even able to
> use a directory effectively

Perhaps you're not aware that directories are not a universal feature of 
filesystems. C has to be able to work on systems where directories 
either don't exist at all, or work very differently to what you're used 
to. (I can think of at least three, two of which I would call major 
commercial systems. The third is Pick, and failing to acknowledge it as 
major may be a touch unfair on it. There are probably more than I can 
bring to mind, of course.)

> and there is NO serious software in C that uses that  minimal subset.

If you define "serious software" as "software that uses extensions", 
you're right. It's hard to see in what other way you could be right. I 
write pretty serious software in C pretty often, and I write it in that 
subset you so disdain. When I do need extensions, which is rare but not 
unheard of, they go into their own module in their own wrapper, so that 
I can easily find the bits I need to re-write for each new system.

> With your attitude there is no software written in C.

Your reliance on extensions is not an imposition on other people's 
ability to cope without them, or to abstract them into isolated modules.

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 1/26/2010 11:00:18 AM

On Jan 26, 4:47=A0am, r...@zedat.fu-berlin.de (Stefan Ram) wrote:
> ld <laurent.den...@gmail.com> writes:
> >>>You don't need a GC, just a richer set of ownership rules.
> >>Yes, please give me the URI of this set!
> >http://cos.cvs.sourceforge.net/viewvc/cos/doc/cos-draft-dls09.pdf
>
> =A0 This seems to be a library that either uses garbage collection
> =A0 or user aided reference counting.

Not a gc but a "kind of reference counting"

There is a difference between reference counting and ownership. The
latter rely on "extended" reference counting to manage automatic
object and static object and should not retain an object referenced
but not owned: e.g. graph's nodes are not retained while graph's
elements are retained. So in practice correct management ownership
means that you stick to DAGs, yes. But there is languages (e.g.
Haskell) where you can only create DAGs, and it doesn't limit their
capabilities.

> =A0 I was hoping for ownership rules for plain C objects or
> =A0 linked C data structures.

I don't see the problem to turn structure into objects (in the OO
sens).

> =A0 C does not have a garbage collector.

Boehm gc. But GCs have other problems:

- memory overhead
- non deterministic finalization
- hidden change in algorithm complexity
- tuned for some "classical use" but could be inefficient for
unexpected cases
- ...

> =A0 A reference counter is an additional subobject that must be
> =A0 added to all objects to be managed in this way.

Right. And as far you have to manage objects (in the OO sens), you
will have to do it in one way or another, this is inherent to objects
with dynamic lifetime. As you will have to bound objects to their
class in OO class-based model.

> =A0 This URI list rules for reference counting with COM (using
> =A0 "AddRef" and "Release"):
>
> http://en.wikipedia.org/wiki/Component_Object_Model#Reference_counting
>
> =A0 And this URI lists some of the problems with reference counting:
>
> http://en.wikipedia.org/wiki/Component_Object_Model#Reference_counting_2

But ownership means no cycle. Two objects cannot _own_ each other. If
you fall into such case, it's probably because the design (or the
understanting of ownership) is incorrect and need to lifting (e.g.
introduce a manager for these objects). Brute reference counting is
dangerous, yes, but ownership isn't. Unfortunately, many programmers
don't make the difference.

> =A0 Another URI:
>
> =A0 =A0 =A0 "Bugs caused by incorrect reference counting in COM
> =A0 =A0 =A0 systems are notoriously hard to resolve"

My rules are _local_ (same scope) so I never have incorrect reference
counting.

a+, ld.
0
Reply Laurent.Deniau (124) 1/26/2010 11:04:56 AM

On Jan 26, 4:04=A0am, Paul Rubin <no.em...@nospam.invalid> wrote:
> Anyway I came late into this thread,

we all came late, the thread started in 2008 ;-)

> but I don't think anyone was
> proposing to embed Haskell as cpp macros or anything like that ;-).

I did something close with COS because once you have implemented loop
in cpp, you get a functional language (with gc) ;-) So I get things
like map, foldl, foldr, filter, etc...

See chaos-pp on sourceforge for a serious lib like this, mine is
focused (and limited) for COS.

> The
> idea is just that it's possible for one's C programs to be influenced by
> functional style, and to implement some nontrivial functional constructs
> through a few coding disciplines supported by some utility functions.

Right. The library of COS is mainly written in a functional style
inspired by Haskell. For example, you can look at

http://cos.cvs.sourceforge.net/viewvc/cos/CosStd/include/cos/gen/algorithm.=
h?view=3Dmarkup

where each generic function (in the CLOS sens) with a 'fun' parameter
expect a functor (closure).

cheers,

ld.

0
Reply Laurent.Deniau (124) 1/26/2010 11:15:51 AM

"Rob Kendrick" <nntp@rjek.com> wrote in message
news:20100126094754.103df758@trite.i.flarn.net.i.flarn.net...
> On Tue, 26 Jan 2010 07:26:49 +0100
> jacob navia <jacob@nospam.org> wrote:
>
>> Your argument that "it is not part of the text of the standard"
>> is just ridiculous. The "C" of the standard is not even able to
>> use a directory effectively and there is NO serious software in C
>> that uses that  minimal subset.
>
> You've heard of Lua, yeah?  http://www.lua.org/  It's a very serious
> piece of software; one of the fastest scripting languages around.

Is it? Just downloaded a copy (5.1.4); only two of the examples provided had
any meaning to me:

FIB.LUA: Fib(36): about 14 seconds (Python: 16 secs, Ruby 8 secs; my own
interpreted language: 1.5 secs)

FACTORIAL.LUA: modified to calculate 12! ten million times: ~250 secs. After
getting rid of some fancy function handling (under the comment 'function 
closures are powerful'), and using straight recursion: ~25 secs (my lang: 
2.6 secs).

Perhaps it's weak on recursion, but then: "i=0; while i<100000000 do i=i+1
end " took ~12 secs (my lang: 0.6 secs)

Just a brief test of course and perhaps I missed out some essential switch
such as /FAST...(I've heard of something called LuaJIT, I doubt this is it
though)

> And
> written entirely in ANSI C with only a handful of concessions (such as
> dlopen to allow for extensions).

I don't use straight ANSI C...

> It's quite easy to write great, reusable, reliable software components
> in ANSI C without reaching for OS-specific extensions.

For interpreter projects, which are really speed critical, I just use
whatever is necessary for performance.

If Lua likes to distribute itself as source code, then I can see some of the
point of restricting itself to a language subset which will compile anywhere
(but I used a binary download, where there shouldn't be a problem with
tweaking to each platform).

-- 
Bartc

0
Reply bartc (783) 1/26/2010 1:51:32 PM

On Tue, 26 Jan 2010 13:51:32 GMT
"bartc" <bartc@freeuk.com> wrote:

> 
> "Rob Kendrick" <nntp@rjek.com> wrote in message
> news:20100126094754.103df758@trite.i.flarn.net.i.flarn.net...
> > On Tue, 26 Jan 2010 07:26:49 +0100
> > jacob navia <jacob@nospam.org> wrote:
> >
> >> Your argument that "it is not part of the text of the standard"
> >> is just ridiculous. The "C" of the standard is not even able to
> >> use a directory effectively and there is NO serious software in C
> >> that uses that  minimal subset.
> >
> > You've heard of Lua, yeah?  http://www.lua.org/  It's a very serious
> > piece of software; one of the fastest scripting languages around.
> 
> Is it? Just downloaded a copy (5.1.4); only two of the examples
> provided had any meaning to me:

The included things are tests, and not optimal examples.  Try the
examples on the alioth shootout:

http://shootout.alioth.debian.org/

Note the comparisons to Python and Ruby.  The mandelbrot one's
especially amusing: the single-threaded Lua implementation is faster
than the multi-threaded Perl one that's using four CPUs.

B.
0
Reply nntp550 (4244) 1/26/2010 2:23:36 PM

Michael Foukarakis wrote:
> On Jan 26, 10:04 am, jacob navia <ja...@nospam.org> wrote:
>> gwowen a �crit :
> 
>>> In many circumstances
>>> a smart pointer is preferable to GC, as it gives a programmer greater
>>> control over deterministic destruction (RAII works a lot better on
>>> managing mutexes than GC, for example -- lock()/unlock() cares about
>>> timing in a way malloc()/free() doesn't).
>> That could be done in C if we had operator overloading, something I have
>> been trying to promote for years.
> 
> Operator overloading and lots of preprocessor tricks, correct?

Operator overloading and constructors/destructors, which are additions 
that Jacob has vehemently opposed in the past.  Smart pointers and RAII 
in general can't work without them.  Even with preprocessor tricks, RAII 
can't be done in C.

-- 
Ian Collins
0
Reply ian-news (9881) 1/26/2010 6:38:09 PM

jacob navia wrote:
> 
> lcc-win proposes a garbage collector in its standard distribution.
> All the problems above are solved with a gc

As they say on the BBC, other distributions with a garbage collector are 
available.  The Boehm GC has been used on many platforms.  It is 
distributed with Sun Studio for example.

I don't see other platforms actively promoting it like you do, perhaps 
they should?  It can be a very useful diagnostic tool as well as a 
collector.

-- 
Ian Collins
0
Reply ian-news (9881) 1/26/2010 6:46:38 PM

Stefan Ram wrote:
> jacob navia <jacob@nospam.org> writes:
>> It depends what "C" you are using.
> 
>   I thought about something along the lines of 
>   ISO/IEC 9899:1999 (E).
> 
Tat is a bit of a silly argument, as Jacob points out, gc is just 
another library.

-- 
Ian Collins
0
Reply ian-news (9881) 1/26/2010 6:49:04 PM

jacob navia <jacob@nospam.org> writes:

> Stefan Ram a écrit :
>>
>>   C does not have a garbage collector.
>>
>
> Many things are left for system libraries, like graphics, network,
> garbage collectors, and many other things like (for instance)
> directory access, thread management, multiprocessing etc.
>
> All of this can be done in C if you do not arbitrarily restrict
> the language to the minimal subset as you are trying to do here.
>
> I have promoted and distributed a garbage collector for C since
> several years. People like you (and the other "regs") have always
> fought this, so your attitude is not surprising.
>
> What is surprising is that now you refuse even to acknowledge that
> a widely distributed implementation of gc exists, and it is used.
>
> Your argument that "it is not part of the text of the standard"
> is just ridiculous. The "C" of the standard is not even able to
> use a directory effectively and there is NO serious software in C
> that uses that  minimal subset.
>
> With your attitude there is no software written in C.

You can do almost everything for a fully featured web application in C.
Even graphics entirely in ISO C (because you generate the graphic file
using standard bit and file handling, and leave it to the browser to
render).

My web site runs on a C scripting language.  It does use some
non-standard libraries, but only in fairly recent incarnations (where I
want some database and other functionality).

Without user editing, you can do everything at the website below in ISO
C.  You read from stdin or getenv, you write to stdout.  You access your
files with fopen etc.  What more do you need.

Oh, and the scripting language uses reference counting, not garbage
collection.  You can do that in standard C as well.
-- 
Online waterways route planner            | http://canalplan.eu
Plan trips, see photos, check facilities  | http://canalplan.org.uk
0
Reply 3-nospam (285) 1/26/2010 6:59:35 PM

Ian Collins <ian-news@hotmail.com> writes:
>>I thought about something along the lines of 
>>ISO/IEC 9899:1999 (E).
>Tat is a bit of a silly argument

  It is not an argument at all, just an answer to a question.

      A: How old are you?
      B: I am twelve years old.
      C: That is a bit of a silly argument.

>, as Jacob points out, gc is just another library.

  I have teaching assignments usually defined by a certain
  language, for example �to teach C (Java, C++, ...)� either
  for beginners or for students who already were in the
  beginners class.

  Since C (Java, C++, ...) already is a field large enough, 
  I fulfil these assignments by teaching the language proper 
  - not any extensions. 

  The students who would like to learn C (Java, C++, ...) also
  would be disappointed when I would use a lot of time to
  teach a special extension library that is available only for
  some operating systems, or is not wanted where they work and
  then NOT teach some parts of the language proper because the
  limited time was spend to teach some extension.

  Therefore, I am interested to learn about any rules
  regarding memory management /that apply when one is using C
  without any extensions/.

0
Reply ram (2827) 1/26/2010 7:07:08 PM

ram@zedat.fu-berlin.de (Stefan Ram) writes:
>I fulfil these assignments by teaching the language proper 

  (including the standard library.)

0
Reply ram (2827) 1/26/2010 7:14:24 PM

Stefan Ram wrote:
> Ian Collins <ian-news@hotmail.com> writes:
>>> I thought about something along the lines of 
>>> ISO/IEC 9899:1999 (E).
>> Tat is a bit of a silly argument
> 
>   It is not an argument at all, just an answer to a question.

Oh come on now, Jacob pointed out that GC is an appropriate tool to use 
when implementing functional concepts in C.  It is in the same way as 
sockets are an appropriate tool if someone wanted to write a 
client/server application in C.

>> , as Jacob points out, gc is just another library.
> 
>   I have teaching assignments usually defined by a certain
>   language, for example �to teach C (Java, C++, ...)� either
>   for beginners or for students who already were in the
>   beginners class.

So you have a set of requirement for your assignment and you stick to 
them.  That doesn't negate the fact that GC is an appropriate tool to 
use when implementing functional concepts in C.  What if your assignment 
were to teach functional concepts in C?

-- 
Ian Collins
0
Reply ian-news (9881) 1/26/2010 7:32:59 PM

jacob navia wrote:

> That could be done in C if we had operator overloading, something I have
> been trying to promote for years.

Why do you need operator overloading in C? Just use C++ in a C-like way,
and be done with it.

robert
0
Reply boblatest2 (238) 1/26/2010 7:49:53 PM

On 2010-01-26, Ian Collins <ian-news@hotmail.com> wrote:
> Stefan Ram wrote:
>> jacob navia <jacob@nospam.org> writes:
>>> It depends what "C" you are using.
>> 
>>   I thought about something along the lines of 
>>   ISO/IEC 9899:1999 (E).
>> 
> Tat is a bit of a silly argument, as Jacob points out, gc is just 
> another library.

.... and, more or less, one that you don't even call!!!

Code written to ISO/IEC 9899 can leak memory, without invoking undefined
behavior, and we can patch that leak by /externally/ imposing garbage
collection.
0
Reply kkylheku (2499) 1/26/2010 11:41:04 PM

Kaz Kylheku wrote:
> On 2010-01-26, Ian Collins <ian-news@hotmail.com> wrote:
>> Stefan Ram wrote:
>>> jacob navia <jacob@nospam.org> writes:
>>>> It depends what "C" you are using.
>>>   I thought about something along the lines of 
>>>   ISO/IEC 9899:1999 (E).
>>>
>> Tat is a bit of a silly argument, as Jacob points out, gc is just 
>> another library.
> 
> ... and, more or less, one that you don't even call!!!
> 
> Code written to ISO/IEC 9899 can leak memory, without invoking undefined
> behavior, and we can patch that leak by /externally/ imposing garbage
> collection.

Unless you have one of the corner cases where garbage collection breaks 
a program.

Also, some types of GC library are unacceptable for some types of 
application because they impose overheads at a time outside your 
control, potentially when you are in a time critical portion of the code.

I can see it being extremely useful in some situations and problematic 
in others.
-- 
Flash Gordon
0
Reply smap (838) 1/27/2010 8:56:25 AM

On Jan 26, 9:49=A0pm, Robert Latest <boblat...@yahoo.com> wrote:
> jacob navia wrote:
> > That could be done in C if we had operator overloading, something I hav=
e
> > been trying to promote for years.
>
> Why do you need operator overloading in C? Just use C++ in a C-like way,
> and be done with it.

But then again, you still need/want a garbage collector (hail
unmanaged environments, folks!), and the lack of automatic memory
management in C++ is yet another reason operator overloading is less
than useful. The other reason is exceptions - but you're supposed to
write exception-safe code by using RAII, which means all pointers have
to be "smart", and their copying semantics always defined, and then
you run into C++'s unbelievably complex static binding rules, you get
depressed, and silently give up.

In general, metaprogramming is orders of magnitude harder to achieve
in C++ than C, because of severely bloated language constructs and
rules. My advice would be to either a) learn to manage your own damned
memory or b) give up C and start learning a language that was made by
people with a good grasp of memory management (Java's a good one on
that matter).

I'm sure you'll agree that since this is comp.lang.c, nobody will
choose option (b) for the foreseeable future. :-)
0
Reply electricdelta (73) 1/27/2010 12:16:54 PM

Michael Foukarakis a �crit :
> On Jan 26, 9:49 pm, Robert Latest <boblat...@yahoo.com> wrote:
>> jacob navia wrote:
>>> That could be done in C if we had operator overloading, something I have
>>> been trying to promote for years.
>> Why do you need operator overloading in C? Just use C++ in a C-like way,
>> and be done with it.
> 
> But then again, you still need/want a garbage collector (hail
> unmanaged environments, folks!), and the lack of automatic memory
> management in C++ is yet another reason operator overloading is less
> than useful. The other reason is exceptions - but you're supposed to
> write exception-safe code by using RAII, which means all pointers have
> to be "smart", and their copying semantics always defined, and then
> you run into C++'s unbelievably complex static binding rules, you get
> depressed, and silently give up.
> 
> In general, metaprogramming is orders of magnitude harder to achieve
> in C++ than C, because of severely bloated language constructs and
> rules. My advice would be to either a) learn to manage your own damned
> memory or b) give up C and start learning a language that was made by
> people with a good grasp of memory management (Java's a good one on
> that matter).
> 
> I'm sure you'll agree that since this is comp.lang.c, nobody will
> choose option (b) for the foreseeable future. :-)

There is option (c), that lcc-win proposes: use the garbage collector!
This allows to write overloaded operators that allocate memory for
new constructs without having any memory leaks in temporary expressions.
0
Reply jacob31 (869) 1/27/2010 2:56:18 PM

On Jan 27, 2:56=A0pm, jacob navia <ja...@spamsink.net> wrote:
> There is option (c), that lcc-win proposes: use the garbage collector!
> This allows to write overloaded operators that allocate memory for
> new constructs without having any memory leaks in temporary expressions.

Or use the Boehm garbage collector with almost any C compiler, or use
Boehm with almost any C++ compiler.  Those who do not understand
history are condemned to repeat it.
0
Reply gwowen (518) 1/27/2010 3:16:35 PM

jacob navia wrote:
> There is option (c), that lcc-win proposes: use the garbage collector!
> This allows to write overloaded operators that allocate memory for
> new constructs without having any memory leaks in temporary expressions.

And your point is...?

If you need a certain functionality in a C program, you have several
options:

1) Link against a third-party library that implements what you need
2) Implement it yourself
3) Switch to a different language that has the feature built-in
4) Invent a C-like language that has the desired features and write
   a full-fledged implementation
5) Convince the Standard Committee to have the desired functionality
   in the next release of the C Standard

You seem to be hell-bent on options 4) and 5) while ordinary mortals are
perfectly happy with 1) thru 3).

So again, what's your point?

robert
0
Reply boblatest2 (238) 1/27/2010 4:42:08 PM

["Followup-To:" header set to comp.lang.c.]
jacob navia wrote:

> lcc-win proposes a garbage collector in its standard distribution.
> All the problems above are solved with a gc

Why insist on "lcc-win" when the garbage collector can be linked into
any C program on any hosted implementation?

robert
0
Reply boblatest2 (238) 1/27/2010 4:46:09 PM

Robert Latest a �crit :
> ["Followup-To:" header set to comp.lang.c.]
> jacob navia wrote:
> 
>> lcc-win proposes a garbage collector in its standard distribution.
>> All the problems above are solved with a gc
> 
> Why insist on "lcc-win" when the garbage collector can be linked into
> any C program on any hosted implementation?
> 
> robert

Because I am the author of that software. I recompiled the work of
Mr Boehm's with lcc-win in 2003 and added it to the standard distribution in 2004.

As far as I know, it was the only C compiler that included a GC in the
standard distribution at that time. I have been promoting the use of a
GC in this group since several years, since I consider it a very good solution
(but not a panacea) in many situations, for instance in this case: functional
style programming.

There are maybe other ports of the collector under windows, but they
are tied to cygwin, as far as I know. The collector compiled with lcc-win
can be used (since it is a dll) with other runtimes, watcom/microsoft, whatever.

Those are some of the reasons I mention my work here.
0
Reply jacob24 (973) 1/27/2010 5:13:39 PM

Robert Latest a �crit :
> jacob navia wrote:
>> There is option (c), that lcc-win proposes: use the garbage collector!
>> This allows to write overloaded operators that allocate memory for
>> new constructs without having any memory leaks in temporary expressions.
> 
> And your point is...?
> 
> If you need a certain functionality in a C program, you have several
> options:
> 
> 1) Link against a third-party library that implements what you need
> 2) Implement it yourself
> 3) Switch to a different language that has the feature built-in
> 4) Invent a C-like language that has the desired features and write
>    a full-fledged implementation
> 5) Convince the Standard Committee to have the desired functionality
>    in the next release of the C Standard
> 
> You seem to be hell-bent on options 4) and 5) while ordinary mortals are
> perfectly happy with 1) thru 3).
> 
> So again, what's your point?
> 
> robert

As you have perfectly seen, Mr "Latest", I am following options (4) and (5).

I am not an ordinary mortal?

I do not think so.

I just suspect that you do not like my work, that's all.
0
Reply jacob24 (973) 1/27/2010 5:16:21 PM

Michael Foukarakis wrote:
> 
> In general, metaprogramming is orders of magnitude harder to achieve
> in C++ than C, because of severely bloated language constructs and
> rules. 

Care to expand on that?

-- 
Ian Collins
0
Reply ian-news (9881) 1/27/2010 6:31:39 PM

jacob navia wrote:
> Robert Latest a �crit :
>> ["Followup-To:" header set to comp.lang.c.]
>> jacob navia wrote:
>>
>>> lcc-win proposes a garbage collector in its standard distribution.
>>> All the problems above are solved with a gc
>>
>> Why insist on "lcc-win" when the garbage collector can be linked into
>> any C program on any hosted implementation?
> 
> Because I am the author of that software. I recompiled the work of
> Mr Boehm's with lcc-win in 2003 and added it to the standard 
> distribution in 2004.
> 
> As far as I know, it was the only C compiler that included a GC in the
> standard distribution at that time. 

Sun's compiler collection has had libgc since the mid-late 90s.

-- 
Ian Collins
0
Reply ian-news (9881) 1/27/2010 6:38:48 PM

Ian Collins a �crit :
> jacob navia wrote:
>> Robert Latest a �crit :
>>> ["Followup-To:" header set to comp.lang.c.]
>>> jacob navia wrote:
>>>
>>>> lcc-win proposes a garbage collector in its standard distribution.
>>>> All the problems above are solved with a gc
>>>
>>> Why insist on "lcc-win" when the garbage collector can be linked into
>>> any C program on any hosted implementation?
>>
>> Because I am the author of that software. I recompiled the work of
>> Mr Boehm's with lcc-win in 2003 and added it to the standard 
>> distribution in 2004.
>>
>> As far as I know, it was the only C compiler that included a GC in the
>> standard distribution at that time. 
> 
> Sun's compiler collection has had libgc since the mid-late 90s.
> 

Thanks. I wasn't aware of that.
0
Reply jacob24 (973) 1/27/2010 6:40:46 PM

Paul Rubin <no.email@nospam.invalid> wrote:

> >   Yes, the whole point of my post is that C usually does /not have/
> >   a GC. So I infer that functional programming, therefore, is
> >   difficult or nearly impossible (beyond a certain level of
> >   complexity) in C.
>
> The functional programming would only work on a certain class of
> objects within the C program, that are collected by an internal gc.
> Sometimes what this leads to is called "Greenspun's Tenth Law" ;-).
>
> There are also so-called conservative gc's for C and C++ (that treat
> all data words as possible heap pointers) but at least as a matter of
> principle, those can be considered unsatisfying.
>
> Anyway I came late into this thread, but I don't think anyone was
> proposing to embed Haskell as cpp macros or anything like that ;-).
> The idea is just that it's possible for one's C programs to be
> influenced by functional style, and to implement some nontrivial
> functional constructs through a few coding disciplines supported by
> some utility functions.

The problem is not garbage collection.  It just makes it even more
complicated.  C is missing some very important high level control
constructs, most notably closures.  The only functional programming you
can do in C is continuation passing style, which is already an
improvement over the usual purely imperative style.  You get some
limited, but safe resource management that way.

I have written an article about that, which you can find here:
<http://blog.ertes.de/2009/02/continuations-for-secure-code.html>.

That article builds on the just-for-fun article, which started this
thread, and turns it into something actually useful.


Greets
Ertugrul


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://blog.ertes.de/

0
Reply es1 (159) 1/27/2010 7:32:06 PM

In article <20100127203206.19bfdcdb@tritium.streitmacht.eu>, Ertugrul =?UTF-8?B?U8O2eWxlbWV6?= <es@ertes.de> writes:

> The problem is not garbage collection.  It just makes it even more
> complicated.  C is missing some very important high level control
> constructs, most notably closures.  The only functional programming you
> can do in C is continuation passing style, which is already an
> improvement over the usual purely imperative style.  You get some
> limited, but safe resource management that way.
> 
> I have written an article about that, which you can find here:
> <http://blog.ertes.de/2009/02/continuations-for-secure-code.html>.

(Since you've mentioned the article here and for me it appears on-topic,
I'll respond here. If you don't mind, I'll quote the function.)

----v----
int withFile(const char *fileName,
             const char *mode,
             int (*user)(FILE *))
{
  FILE *fh;
  int err;

  fh = fopen(fileName, mode);
  if (fh == NULL) return 1;

  err = user(fh);
  fclose(fh);
  return err;
}
----^----

You don't check the return value of fclose(). If the last operation in
(*user)(fh) was a write that remained buffered (_IOFBF/_IOLBF), then the
current fclose() invocation can lead to silent data loss. In my view,
either the return value of fclose() should be checked in withFile(), or
the user callback should be made explicitly responsible to close up shop
with an fflush().

Perhaps you've omitted the check for simplicity's sake, but -- if I
understand it correctly -- the point of the article is exactly to move
the responsibility of closing file handles (and to do so correctly) from
the programmer to the RTS (run-time system).

If, indeed, the run-time system cannot "talk back" to the programmer by
design, then there's no way around flushing the stdio stream within
(*user)(fh). In that vein, if a program (in general) ever wrote to
stdout, it should explicitly flush it before exiting with EXIT_SUCCESS,
so that at least the return status can be changed to EXIT_FAILURE or
some such in the last minute.

[not standard C] This approach is obviously not sufficient for
hardware-level data safety (many times not even fsync() suffices for
that, allegedly), but it does warn about "disk full", "maximum file size
exceeded" and similar software conditions.

Digressing even more off topic,

(1) The same holds for manipulating (usually regular) files through file
descriptors: NFS servers tend to buffer up writes until the final
close(). At least a checked close(STDOUT_FILENO) is necessary in filter
programs if the process is about to exit successfully.

(2) This is why putting close / flush operations and the like in C++
destructors qualifies as a bad idea. Destructors must not throw any
exceptions and are unable to return values, so there's no easy way for
them to communicate failure back to the programmer. I guess they could
modify some non-member objects, but destructors exist so that the
programmer can largely forget about manually destroying objects.

(3) Garbage collection (in Java) usually delays the release of the
memory allocated for the object and the execution of the corresponding
destructor (finalizer) until the garbage collector sees fit.
Unfortunately, this can delay the release of other (remarkably
non-memory) resources; thus the garbage collector holds back types of
resources it has nothing to do with. The programmer best calls some
close() method manually, completely defeating the purpose of garbage
collection and exceptions.

http://stackoverflow.com/questions/171952/is-there-a-destructor-for-java/171957#171957

-o-

If I deliberately ignore the scalar value returned by a function call, I
like to write

    (void)fun(...);

as shown in C90 6.6.3 "Expression and null statements" (or C99 6.8.3
"Expression and null statements"), Example 1:

----v----
If a function call is evaluated as an expression statement for its side
effects only, the discarding of its value may be made explicit by
converting the expression to a void expression by means of a cast:

    int p(int);
    /*...*/
    (void)p(0);
----^----


Cheers,
lacos
0
Reply lacos (176) 1/27/2010 9:57:48 PM

On 27 jan, 20:32, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
> Paul Rubin <no.em...@nospam.invalid> wrote:
> > > =A0 Yes, the whole point of my post is that C usually does /not have/
> > > =A0 a GC. So I infer that functional programming, therefore, is
> > > =A0 difficult or nearly impossible (beyond a certain level of
> > > =A0 complexity) in C.
>
> > The functional programming would only work on a certain class of
> > objects within the C program, that are collected by an internal gc.
> > Sometimes what this leads to is called "Greenspun's Tenth Law" ;-).
>
> > There are also so-called conservative gc's for C and C++ (that treat
> > all data words as possible heap pointers) but at least as a matter of
> > principle, those can be considered unsatisfying.
>
> > Anyway I came late into this thread, but I don't think anyone was
> > proposing to embed Haskell as cpp macros or anything like that ;-).
> > The idea is just that it's possible for one's C programs to be
> > influenced by functional style, and to implement some nontrivial
> > functional constructs through a few coding disciplines supported by
> > some utility functions.
>
> The problem is not garbage collection. =A0It just makes it even more
> complicated. =A0C is missing some very important high level control
> constructs, most notably closures. =A0The only functional programming you
> can do in C is continuation passing style, which is already an
> improvement over the usual purely imperative style. =A0You get some
> limited, but safe resource management that way.
>
> I have written an article about that, which you can find here:
> <http://blog.ertes.de/2009/02/continuations-for-secure-code.html>.
>
> That article builds on the just-for-fun article, which started this
> thread, and turns it into something actually useful.

you should remove "This is impossible in C" from the last line of your
article since with my C lib, I use closures as I would in FP. For
example:

Haskell:
    fmap (\x -> fmap (\y -> fmap (\z -> fun3 x y z) zs) ys) xs

C Object System:
    gmap(gmap(gmap(fun3(aLzy2(__1), aLzy(__1), __1), zs), ys), xs)

The main difference is that Haskell closures have lexical scoping and
lazy evaluation while COS closures have dynamic scoping (placeholders)
and C has strict evaluation. This is why you need to delay the
evaluation of the closure' arguments to the proper evaluation
environment (e.g. geval) using the aLzy() qualifier:

aLzy2(__1) -> 1st argument of the outer  map <=3D> x
aLzy (__1) -> 1st argument of the middle map <=3D> y
      __1  -> 1st argument of the inner  map <=3D> z

Dynamic scoping also means that you can build the closure outside the
lexical scope:

OBJ fun =3D fun3(aLzy2(__1), aLzy(__1), __1);
gmap(gmap(gmap(fun, zs), ys), xs);

is also valid (and impossible in Haskell AFAIK).

regards,

ld.
0
Reply Laurent.Deniau (124) 1/27/2010 11:00:47 PM

ld <laurent.deniau@gmail.com> wrote:

> On 27 jan, 20:32, Ertugrul S=C3=B6ylemez <e...@ertes.de> wrote:
> > The problem is not garbage collection. =C2=A0It just makes it even more
> > complicated. =C2=A0C is missing some very important high level control
> > constructs, most notably closures. =C2=A0The only functional programming
> > you can do in C is continuation passing style, which is already an
> > improvement over the usual purely imperative style. =C2=A0You get some
> > limited, but safe resource management that way.
> >
> > I have written an article about that, which you can find here:
> > <http://blog.ertes.de/2009/02/continuations-for-secure-code.html>.
> >
> > That article builds on the just-for-fun article, which started this
> > thread, and turns it into something actually useful.
>
> you should remove "This is impossible in C" from the last line of your
> article since with my C lib, I use closures as I would in FP. For
> example:
>
> Haskell:
>     fmap (\x -> fmap (\y -> fmap (\z -> fun3 x y z) zs) ys) xs
>
> C Object System:
>     gmap(gmap(gmap(fun3(aLzy2(__1), aLzy(__1), __1), zs), ys), xs)

Of course you can always write an interpreter for a richer language.
That's not really 'doing it in C'.  Just look at glib, which implements
a complete object oriented language on top of C.  You're developing in
your higher language, which is expressed in terms of C.


> The main difference is that Haskell closures have lexical scoping and
> lazy evaluation while COS closures have dynamic scoping (placeholders)
> and C has strict evaluation. This is why you need to delay the
> evaluation of the closure' arguments to the proper evaluation
> environment (e.g. geval) using the aLzy() qualifier:
>
> aLzy2(__1) -> 1st argument of the outer  map <=3D> x
> aLzy (__1) -> 1st argument of the middle map <=3D> y
>       __1  -> 1st argument of the inner  map <=3D> z
>
> Dynamic scoping also means that you can build the closure outside the
> lexical scope:
>
> OBJ fun =3D fun3(aLzy2(__1), aLzy(__1), __1);
> gmap(gmap(gmap(fun, zs), ys), xs);
>
> is also valid (and impossible in Haskell AFAIK).

It's not impossible.  Your closure can be a stateful computation:

  myClosure =3D do
    x <- gets var1
    y <- gets var2
    return (x+y)

In can also alter that surrounding state this way.  Adding the
continuation monad it can even escape into its current context:

  myClosure escape =3D do
    x <- lift get
    when (x =3D=3D 2) (escape True)
    return False

The 'escape' function may be a continuation, so the caller can instruct
this function to escape anywhere he wants, if the state happens to be 2.
I use this often to escape from 'forever' computations to a higher
context (which may even be unknown at that point).

I don't think that you can construct any control structure in C, which
can't be expressed easily in Haskell.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 1/28/2010 6:13:24 AM

Ertugrul Söylemez <es@ertes.de> writes:
> I don't think that you can construct any control structure in C, which
> can't be expressed easily in Haskell.

Interrupt handler?
0
Reply no.email6 (1518) 1/28/2010 6:43:35 AM

Paul Rubin <no.email@nospam.invalid> wrote:

> Ertugrul S=C3=B6ylemez <es@ertes.de> writes:
> > I don't think that you can construct any control structure in C,
> > which can't be expressed easily in Haskell.
>
> Interrupt handler?

That's not a control structure.  In fact it's rather an "out of control"
structure.  How you handle interrupts depends on the context.  If you're
using an operating system, you can use signal handlers or operating
system functions for that.  Some interrupts are converted to exceptions
in many languages.  There is no difference to C here, except that you
don't have exceptions in C and you can exploit Haskell's concurrency
system, which is also missing in C.

If instead you're _writing_ an operating system, it depends on what your
hardware abstractions look like.  See House [1] for an example.  So yes,
these things are well possible to do in Haskell.

[1] http://programatica.cs.pdx.edu/House/


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 1/28/2010 7:41:08 AM

On Jan 27, 8:31 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> Michael Foukarakis wrote:
>
> > In general, metaprogramming is orders of magnitude harder to achieve
> > in C++ than C, because of severely bloated language constructs and
> > rules.
>
> Care to expand on that?

I'll be as brief as I can:

- Implicit type conversions. How the following example compiles OK
without a warning is beyond me:
#include <iostream>
void foo(const std::string &) {}
int main()
{
    foo(false);
}

- The "type name or object name?" issue is one of the little things
that can make parsing C++ a nightmare. You can get different parse
trees based on the output of sizeof, for instance. And sizeof is
dependent on the platform and implementation of inheritance, virtual
functions, etc.
- Current programming idioms (in C++, that is) and its lack of
reflection force us to use static binding to implement polymorphism.
So, for a common and seemingly simple application of metaprogramming,
such as printing objects at runtime, you'll get N layers of syntax and
meticulously placed overloads of operator<< in carefully #include'd
header files, and even in that case some compilers will generate
erroneous code without as much as a warning (that is, if they got past
the implicit type conversion hell).
- The conscious decision of not adding high-level types has led to,
most significantly, lack of easy-to-use containers. It has its
upsides, I agree. However, when you get around to use (and not
implement) ADTs, debugging can be a bitch. And when it comes to
implementation, at the heart of every high-level container you'll find
templates, relatively sophisticated ones too in case you're dealing
with the standard library and even more so with the Swiss army knife
that's called Boost. Everyone knows in what ways templates suck, I
won't list them.
- Duplicate facilities. For everything from printing to initializing
an object to using an array. They don't interoperate very well (check
out some code dealing with char* and std::string if you feel like
getting an aneurysm), and for that reason the C++ crowd shuns the use
of C syntax and features in C++ programs, although they still claim
compatibility with C is a good thing. I always chuckle when I see that
written. Heh.
- Manual memory management. A good thing. I support this 100%. It has
its place in the language and in today's systems. But it's
incompatible with templates and operator overloading. Can't have it
all (maybe in another language :).
- Inlining, although not as much related to metaprogramming as the
ones above. For this part, I'm quoting: "People define large functions
inline for two reasons. Some of them "care" (emotionally) about
performance, but never actually measure it, and someone told them that
inlining speeds things up, and forgot to tell them how it can slow
them down." Like when inline functions are implicitly called or
generated. Sometimes you'll have a huge class that needs to be
accessible globally. A singleton, I hear you saying! Nah, perhaps
other facilities of your program need to notify it, or modify it, and
others need to see the changes. Anyway that huge class will at least
get created and destroyed once. But that class will probably have no
constructor, no destructor, no operator= either - the compiler will
generate code for those anyway. And that may not be a problem until
you crash nearby and get a pile of assembly (which you haven't
written, it's not even your compiled code!) without any diagnostics
whatsoever.

I mean, those are just a few. I've seen literally thousands of
complaints about the language constructs, and sadly most came from
people who were way more knowledgeable than me on the issues at hand.
It's not that C++ is bad, it's very useful and rewards you when you're
not overzealous, but it's unsuitable for certain types of problems,
for which it's (sadly, again) used for very often. That's one of the
disadvantages of people calling it Object Oriented, without actually
being such in a satisfying degree, I guess. At least BS is less stuck
up than most people, when it comes to it.

Bah, sorry for the wall of text. I guess I couldn't help it. :-)
0
Reply electricdelta (73) 1/28/2010 8:09:13 AM

Ertugrul Söylemez <es@ertes.de> writes:

> Paul Rubin <no.email@nospam.invalid> wrote:
>
>> >   Yes, the whole point of my post is that C usually does /not have/
>> >   a GC. So I infer that functional programming, therefore, is
>> >   difficult or nearly impossible (beyond a certain level of
>> >   complexity) in C.
>>
>> The functional programming would only work on a certain class of
>> objects within the C program, that are collected by an internal gc.
>> Sometimes what this leads to is called "Greenspun's Tenth Law" ;-).
>>
>> There are also so-called conservative gc's for C and C++ (that treat
>> all data words as possible heap pointers) but at least as a matter of
>> principle, those can be considered unsatisfying.
>>
>> Anyway I came late into this thread, but I don't think anyone was
>> proposing to embed Haskell as cpp macros or anything like that ;-).
>> The idea is just that it's possible for one's C programs to be
>> influenced by functional style, and to implement some nontrivial
>> functional constructs through a few coding disciplines supported by
>> some utility functions.
>
> The problem is not garbage collection.  It just makes it even more
> complicated.  C is missing some very important high level control
> constructs, most notably closures.  The only functional programming you
> can do in C is continuation passing style, which is already an
> improvement over the usual purely imperative style.  You get some
> limited, but safe resource management that way.
>
> I have written an article about that, which you can find here:
> <http://blog.ertes.de/2009/02/continuations-for-secure-code.html>.
>
> That article builds on the just-for-fun article, which started this
> thread, and turns it into something actually useful.

Commenting there is so painful (the comment editor embedded in the page
doesn't recognise arrow keys!) I'll reply here instead!

It's an interesting approach, and I can certainly see its value in a
structure that requires a lot of specialised initialisation and
destruction.  You could replace: 

struct foo *foop = Create_Foo_Structure(); 
lots-and-lots-of-code-using foop
Release_Foo_Structure(foop)

with

withFoo(dofoopstuff);

but, of course, you have to create dofoopstuff(struct foo *foop) before
you can do that, and in that case writing:

struct foo *foop = Create_Foo_Structure(); 
dofoopstuff(foop);
Release_Foo_Structure(foop)

does the same job, and you aren't likely to forget to release it when
it's only two lines from creation.

And that's where I think this fails.  If this is the only benefit you
get (in C obviously - I know some of the stuff you can do in a better
framework) then it doesn't seem to give anything more than a programming
discipline that says:
- remove anything that uses an allocated structure (including a file
pointer) into a separate function.
- call the function immediately between allocation and release of the
structures, and don't place /any/ other code in there.

Still a neat idea, but I'm not convinced it normally has any practical
value.
-- 
Online waterways route planner            | http://canalplan.eu
Plan trips, see photos, check facilities  | http://canalplan.org.uk
0
Reply 3-nospam (285) 1/28/2010 8:26:50 AM

On 27 Jan, 21:57, la...@ludens.elte.hu (Ersek, Laszlo) wrote:
> In article <20100127203206.19bfd...@tritium.streitmacht.eu>, Ertugrul =3D=
?UTF-8?B?U8O2eWxlbWV6?=3D <e...@ertes.de> writes:


> > The problem is not garbage collection. =A0It just makes it even more
> > complicated. =A0C is missing some very important high level control
> > constructs, most notably closures. =A0The only functional programming y=
ou
> > can do in C is continuation passing style, which is already an
> > improvement over the usual purely imperative style. =A0You get some
> > limited, but safe resource management that way.
>
> > I have written an article about that, which you can find here:
> > <http://blog.ertes.de/2009/02/continuations-for-secure-code.html>.
>
> (Since you've mentioned the article here and for me it appears on-topic,
> I'll respond here. If you don't mind, I'll quote the function.)
>
> ----v----
> int withFile(const char *fileName,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0const char *mode,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0int (*user)(FILE *))
> {
> =A0 FILE *fh;
> =A0 int err;
>
> =A0 fh =3D fopen(fileName, mode);
> =A0 if (fh =3D=3D NULL) return 1;
>
> =A0 err =3D user(fh);
> =A0 fclose(fh);
> =A0 return err;}
>
> ----^----
>
> You don't check the return value of fclose().

what do you do if fclose() fails? Admittedly withFile() shouldn't be
ignoring the fclose(), we might one to tell the user that his last
transaction hasn't gone into the master record!


> If the last operation in
> (*user)(fh) was a write that remained buffered (_IOFBF/_IOLBF), then the
> current fclose() invocation can lead to silent data loss. In my view,
> either the return value of fclose() should be checked in withFile(), or
> the user callback should be made explicitly responsible to close up shop
> with an fflush().

if fclose() doesn't work why should fflush()?

<snip>

> (2) This is why putting close / flush operations and the like in C++
> destructors qualifies as a bad idea. Destructors must not throw any
> exceptions and are unable to return values, so there's no easy way for
> them to communicate failure back to the programmer. I guess they could
> modify some non-member objects, but destructors exist so that the
> programmer can largely forget about manually destroying objects.

but dtors become much less useful if they don't clean up. RAII doesn't
work any more.

<snip>

> -o-
>
> If I deliberately ignore the scalar value returned by a function call, I
> like to write
>
> =A0 =A0 (void)fun(...);
>
> as shown in C90 6.6.3 "Expression and null statements" (or C99 6.8.3
> "Expression and null statements"), Example 1:
>
> ----v----
> If a function call is evaluated as an expression statement for its side
> effects only, the discarding of its value may be made explicit by
> converting the expression to a void expression by means of a cast:
>
> =A0 =A0 int p(int);
> =A0 =A0 /*...*/
> =A0 =A0 (void)p(0);
> ----^----

I think this is an ugly and clutterd coding style



--
"Reports that say that something hasn't happened are always
interesting to me,
because as we know, there are known knowns; there are things we know
we know.
We also know there are known unknowns; that is to say we know there
are some
things we do not know. But there are also unknown unknowns
-- the ones we don't know we don't know."
       (Rumsfeld)

0
Reply nick_keighley_nospam (4574) 1/28/2010 8:28:28 AM

Michael Foukarakis wrote:
> On Jan 27, 8:31 pm, Ian Collins <ian-n...@hotmail.com> wrote:
>> Michael Foukarakis wrote:
>>
>>> In general, metaprogramming is orders of magnitude harder to achieve
>>> in C++ than C, because of severely bloated language constructs and
>>> rules.
>> Care to expand on that?
> 
> I'll be as brief as I can:
> 
<snip>

> - Current programming idioms (in C++, that is) and its lack of
> reflection force us to use static binding to implement polymorphism.
> So, for a common and seemingly simple application of metaprogramming,
> such as printing objects at runtime, you'll get N layers of syntax and
> meticulously placed overloads of operator<< in carefully #include'd
> header files, and even in that case some compilers will generate
> erroneous code without as much as a warning (that is, if they got past
> the implicit type conversion hell).

How does this relate to a comparison of metaprogramming in C and C++?

> - The conscious decision of not adding high-level types has led to,
> most significantly, lack of easy-to-use containers. It has its
> upsides, I agree. However, when you get around to use (and not
> implement) ADTs, debugging can be a bitch. And when it comes to
> implementation, at the heart of every high-level container you'll find
> templates, relatively sophisticated ones too in case you're dealing
> with the standard library and even more so with the Swiss army knife
> that's called Boost. Everyone knows in what ways templates suck, I
> won't list them.

Again, I don't see how this is harder than C, which doesn't have 
high-level types either.

> - Duplicate facilities. For everything from printing to initializing
> an object to using an array. They don't interoperate very well (check
> out some code dealing with char* and std::string if you feel like
> getting an aneurysm), and for that reason the C++ crowd shuns the use
> of C syntax and features in C++ programs, although they still claim
> compatibility with C is a good thing. I always chuckle when I see that
> written. Heh.

Do they? I've never come across that.

> - Manual memory management. A good thing. I support this 100%. It has
> its place in the language and in today's systems. But it's
> incompatible with templates and operator overloading. Can't have it
> all (maybe in another language :).

How?

<snip>

> I mean, those are just a few. I've seen literally thousands of
> complaints about the language constructs, and sadly most came from
> people who were way more knowledgeable than me on the issues at hand.
> It's not that C++ is bad, it's very useful and rewards you when you're
> not overzealous, but it's unsuitable for certain types of problems,
> for which it's (sadly, again) used for very often. That's one of the
> disadvantages of people calling it Object Oriented, without actually
> being such in a satisfying degree, I guess. At least BS is less stuck
> up than most people, when it comes to it.

Yet again, I don see how this relates to a comparison with C.

-- 
Ian Collins
0
Reply ian-news (9881) 1/28/2010 8:32:00 AM

On Jan 28, 10:32=A0am, Ian Collins <ian-n...@hotmail.com> wrote:
> Michael Foukarakis wrote:
> > On Jan 27, 8:31 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> >> Michael Foukarakis wrote:
>
> >>> In general, metaprogramming is orders of magnitude harder to achieve
> >>> in C++ than C, because of severely bloated language constructs and
> >>> rules.
> >> Care to expand on that?
>
> > I'll be as brief as I can:
>
> <snip>
>
> > - Current programming idioms (in C++, that is) and its lack of
> > reflection force us to use static binding to implement polymorphism.
> > So, for a common and seemingly simple application of metaprogramming,
> > such as printing objects at runtime, you'll get N layers of syntax and
> > meticulously placed overloads of operator<< in carefully #include'd
> > header files, and even in that case some compilers will generate
> > erroneous code without as much as a warning (that is, if they got past
> > the implicit type conversion hell).
>
> How does this relate to a comparison of metaprogramming in C and C++?

I assume you're aware of the definition of metaprogramming. In C++,
you have to deal with the use cases I described above. In C, you
don't, since the concept of polymorphism, overloading, templates are
not there. There's your extra complexity.

> > - The conscious decision of not adding high-level types has led to,
> > most significantly, lack of easy-to-use containers. It has its
> > upsides, I agree. However, when you get around to use (and not
> > implement) ADTs, debugging can be a bitch. And when it comes to
> > implementation, at the heart of every high-level container you'll find
> > templates, relatively sophisticated ones too in case you're dealing
> > with the standard library and even more so with the Swiss army knife
> > that's called Boost. Everyone knows in what ways templates suck, I
> > won't list them.
>
> Again, I don't see how this is harder than C, which doesn't have
> high-level types either.

Again, more complex language constructs to manage. I don't see how I
could've made this any simpler, sorry.

> > - Duplicate facilities. For everything from printing to initializing
> > an object to using an array. They don't interoperate very well (check
> > out some code dealing with char* and std::string if you feel like
> > getting an aneurysm), and for that reason the C++ crowd shuns the use
> > of C syntax and features in C++ programs, although they still claim
> > compatibility with C is a good thing. I always chuckle when I see that
> > written. Heh.
>
> Do they? I've never come across that.

Well, maybe I've come across some particularly bad code then.

> > - Manual memory management. A good thing. I support this 100%. It has
> > its place in the language and in today's systems. But it's
> > incompatible with templates and operator overloading. Can't have it
> > all (maybe in another language :).
>
> How?

Here's a quick example:

Matrix add(const Matrix& x, const Matrix& y);
Matrix operator+(const Matrix& x, const Matrix& y);
Matrix use_add(const Matrix& a, const Matrix& b, const Matrix& c)
{
  return add(a,add(b,c));
}
Matrix use_plus(const Matrix& a, const Matrix& b, const Matrix& c)
{
  return a + b + c;
}

Now for the philosophical question: Where does The Matrix live?

- is it allocated by new and returned by reference? Who is supposed to
clean it up? Who manages the temporaries created by a+b+c ?
- is it returned by value? Won't the copy constructor copy lots of
matrices then? Not particularly pleasant when it comes to matrix
operations (which will be quite a lot if you're actually aiming for a
usable Matrix class - I assume I don't have to show you applications
of matrices as well).

Now consider what happens when overloaded operators may fail. There's
no good way to return an error, there are no context-free matrix "bad
values", because the whole point of operator+ is to be able to write (a
+b+c+d)..Go ahead, throw an exception. Throw it in a templated
constructor. Feel the madness. :-)

>
> > I mean, those are just a few. I've seen literally thousands of
> > complaints about the language constructs, and sadly most came from
> > people who were way more knowledgeable than me on the issues at hand.
> > It's not that C++ is bad, it's very useful and rewards you when you're
> > not overzealous, but it's unsuitable for certain types of problems,
> > for which it's (sadly, again) used for very often. That's one of the
> > disadvantages of people calling it Object Oriented, without actually
> > being such in a satisfying degree, I guess. At least BS is less stuck
> > up than most people, when it comes to it.
>
> Yet again, I don see how this relates to a comparison with C.

Have you tried any of the above in practice? Some non-trivial project
with more than a pair of developers? I'm sure that if you did, you'd
find it pretty daunting. Maybe not impossible to achieve, but not
without major compromises in your requirements.
0
Reply electricdelta (73) 1/28/2010 8:55:17 AM

Michael Foukarakis wrote:
> On Jan 28, 10:32 am, Ian Collins <ian-n...@hotmail.com> wrote:
>> Michael Foukarakis wrote:
>>> On Jan 27, 8:31 pm, Ian Collins <ian-n...@hotmail.com> wrote:
>>>> Michael Foukarakis wrote:
>>>>> In general, metaprogramming is orders of magnitude harder to achieve
>>>>> in C++ than C, because of severely bloated language constructs and
>>>>> rules.
>>>> Care to expand on that?
>>> I'll be as brief as I can:
>> <snip>
>>
>>> - Current programming idioms (in C++, that is) and its lack of
>>> reflection force us to use static binding to implement polymorphism.
>>> So, for a common and seemingly simple application of metaprogramming,
>>> such as printing objects at runtime, you'll get N layers of syntax and
>>> meticulously placed overloads of operator<< in carefully #include'd
>>> header files, and even in that case some compilers will generate
>>> erroneous code without as much as a warning (that is, if they got past
>>> the implicit type conversion hell).
>> How does this relate to a comparison of metaprogramming in C and C++?
> 
> I assume you're aware of the definition of metaprogramming. In C++,
> you have to deal with the use cases I described above. In C, you
> don't, since the concept of polymorphism, overloading, templates are
> not there. There's your extra complexity.

Ah, I see where the confusion lies, when you wrote "metaprogramming is 
orders of magnitude harder to achieve in C++ than C" I assumed you were 
referring to the metalanguage, rather than the object language.  Neither 
can be their own metalanguage.

> Have you tried any of the above in practice? Some non-trivial project
> with more than a pair of developers? I'm sure that if you did, you'd
> find it pretty daunting. Maybe not impossible to achieve, but not
> without major compromises in your requirements.

Oh I've worked on and managed large C++ projects and yes it can be 
daunting, but also rewarding!

-- 
Ian Collins
0
Reply ian-news (9881) 1/28/2010 9:42:51 AM

On Jan 28, 11:42=A0am, Ian Collins <ian-n...@hotmail.com> wrote:
> Michael Foukarakis wrote:
> > On Jan 28, 10:32 am, Ian Collins <ian-n...@hotmail.com> wrote:
> >> Michael Foukarakis wrote:
> >>> On Jan 27, 8:31 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> >>>> Michael Foukarakis wrote:
> >>>>> In general, metaprogramming is orders of magnitude harder to achiev=
e
> >>>>> in C++ than C, because of severely bloated language constructs and
> >>>>> rules.
> >>>> Care to expand on that?
> >>> I'll be as brief as I can:
> >> <snip>
>
> >>> - Current programming idioms (in C++, that is) and its lack of
> >>> reflection force us to use static binding to implement polymorphism.
> >>> So, for a common and seemingly simple application of metaprogramming,
> >>> such as printing objects at runtime, you'll get N layers of syntax an=
d
> >>> meticulously placed overloads of operator<< in carefully #include'd
> >>> header files, and even in that case some compilers will generate
> >>> erroneous code without as much as a warning (that is, if they got pas=
t
> >>> the implicit type conversion hell).
> >> How does this relate to a comparison of metaprogramming in C and C++?
>
> > I assume you're aware of the definition of metaprogramming. In C++,
> > you have to deal with the use cases I described above. In C, you
> > don't, since the concept of polymorphism, overloading, templates are
> > not there. There's your extra complexity.
>
> Ah, I see where the confusion lies, when you wrote "metaprogramming is
> orders of magnitude harder to achieve in C++ than C" I assumed you were
> referring to the metalanguage, rather than the object language. =A0Neithe=
r
> can be their own metalanguage.
>
> > Have you tried any of the above in practice? Some non-trivial project
> > with more than a pair of developers? I'm sure that if you did, you'd
> > find it pretty daunting. Maybe not impossible to achieve, but not
> > without major compromises in your requirements.
>
> Oh I've worked on and managed large C++ projects and yes it can be
> daunting, but also rewarding!

True. In cash, too. :P
0
Reply electricdelta (73) 1/28/2010 9:49:06 AM

On Jan 28, 7:13=A0am, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
> ld <laurent.den...@gmail.com> wrote:
> > On 27 jan, 20:32, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
> > > The problem is not garbage collection. =A0It just makes it even more
> > > complicated. =A0C is missing some very important high level control
> > > constructs, most notably closures. =A0The only functional programming
> > > you can do in C is continuation passing style, which is already an
> > > improvement over the usual purely imperative style. =A0You get some
> > > limited, but safe resource management that way.
>
> > > I have written an article about that, which you can find here:
> > > <http://blog.ertes.de/2009/02/continuations-for-secure-code.html>.
>
> > > That article builds on the just-for-fun article, which started this
> > > thread, and turns it into something actually useful.
>
> > you should remove "This is impossible in C" from the last line of your
> > article since with my C lib, I use closures as I would in FP. For
> > example:
>
> > Haskell:
> > =A0 =A0 fmap (\x -> fmap (\y -> fmap (\z -> fun3 x y z) zs) ys) xs
>
> > C Object System:
> > =A0 =A0 gmap(gmap(gmap(fun3(aLzy2(__1), aLzy(__1), __1), zs), ys), xs)
>
> Of course you can always write an interpreter for a richer language.
> That's not really 'doing it in C'. =A0Just look at glib, which implements
> a complete object oriented language on top of C. =A0You're developing in
> your higher language, which is expressed in terms of C.

Yes, that is a DSL but more general than usually done since its goal
is to extend the programming paradigms available in C. So for you, the
hundred of so DSL developed on top of Haskell are not Haskell?
Text.Printf is not Haskell? Yes, DSL are usually hackish, but there is
good advantage to stay with the same language.

> > The main difference is that Haskell closures have lexical scoping and
> > lazy evaluation while COS closures have dynamic scoping (placeholders)
> > and C has strict evaluation. This is why you need to delay the
> > evaluation of the closure' arguments to the proper evaluation
> > environment (e.g. geval) using the aLzy() qualifier:
>
> > aLzy2(__1) -> 1st argument of the outer =A0map <=3D> x
> > aLzy (__1) -> 1st argument of the middle map <=3D> y
> > =A0 =A0 =A0 __1 =A0-> 1st argument of the inner =A0map <=3D> z
>
> > Dynamic scoping also means that you can build the closure outside the
> > lexical scope:
>
> > OBJ fun =3D fun3(aLzy2(__1), aLzy(__1), __1);
> > gmap(gmap(gmap(fun, zs), ys), xs);
>
> > is also valid (and impossible in Haskell AFAIK).
>
> It's not impossible. =A0Your closure can be a stateful computation:
>
> =A0 myClosure =3D do
> =A0 =A0 x <- gets var1
> =A0 =A0 y <- gets var2
> =A0 =A0 return (x+y)

But then you have to encapsulate fmap elements into the State monad
since you use is as a kind of placeholder...

> In can also alter that surrounding state this way. =A0Adding the
> continuation monad it can even escape into its current context:
>
> =A0 myClosure escape =3D do
> =A0 =A0 x <- lift get
> =A0 =A0 when (x =3D=3D 2) (escape True)
> =A0 =A0 return False
>
> The 'escape' function may be a continuation, so the caller can instruct
> this function to escape anywhere he wants, if the state happens to be 2.
> I use this often to escape from 'forever' computations to a higher
> context (which may even be unknown at that point).

Yep, this is the way Haskell manage exception AFAIK.

> I don't think that you can construct any control structure in C, which
> can't be expressed easily in Haskell.

you mean something like:

defmethod(OBJ, ifThenElse, TrueFalse, Functor, Functor)
  retmethod(_1 =3D=3D True ? geval(_2) : geval(_3));
endmethod

The second expression (held by _3) remains unevaluated if the boolean
(_1) is False. Comparing to Haskell, you have to force laziness as in
the previous example to break strict evaluation of C. But this is also
true in almost all language except haskell (e.g. scheme).

regards,

ld.


0
Reply Laurent.Deniau (124) 1/28/2010 11:25:52 AM

> Here's a quick example:
>
> Now for the philosophical question: Where does The Matrix live?

> - is it allocated by new and returned by reference?

It behaves "as if" it were created as an "auto" and copied on
assignment.

> Who is supposed to clean it up?

Whoever takes a copy cleans up their own copy.

> Who manages the temporaries created by a+b+c ?

RAII.  They're automatically destroyed once they're used.

> - is it returned by value?

It is "as if" it is, yes.

> Won't the copy constructor copy lots of matrices then?

Only if the compiler cannot optimise the assignment away, while still
behaving "as if" there were lots of copies.  Most compilers (even C
compilers) don't return large structures on the stack or in registers,
but use a hidden reference argument, so most compilers elide the
copies.   See RVO and NRVO.

Of course, if you implement operator+=, you can elide those copies
yourself.

> Go ahead, throw an exception. Throw it in a templated
> constructor.

OK.  I will.

> Feel the madness. :-)

Non-sequitor.

> > > I mean, those are just a few. I've seen literally thousands of
> > > complaints about the language constructs,

Whoop-de-do.  I've seen literally thousands of complaints about almost
everything.  People like complaining.  Can you name me a language
about which vociferous angry people do not frequently complain?

> Have you tried any of the above in practice?

Yup

> Some non-trivial project with more than a pair of developers?

Yup

> I'm sure that if you did, you'd find it pretty daunting.

Not massively.  You're not obliged to use every feature of the
language, and if you try to in C++, it will drive you insane.  If
you're talking about doing heavily-templated-metaprogramming without
understanding RVO, you might be trying to run before you can walk. But
good design, a bit of care and a lot of restraint will see you through.
0
Reply gwowen (518) 1/28/2010 3:35:06 PM

lacos@ludens.elte.hu (Ersek, Laszlo) writes:
>int withFile(const char *fileName,
>             const char *mode,
>             int (*user)(FILE *))
>{
>  FILE *fh;
>  int err;

>  fh = fopen(fileName, mode);
>  if (fh == NULL) return 1;

>  err = user(fh);
>  fclose(fh);
>  return err;
>}

  Sometimes, an additional fourth parameter for a client data
  object (as in �err = user( fh, data )�) might come in handy.

  The function �user� should not give a meaning to the result
  value �1� as this could be confused with the indication for
  �fh == NULL�. When such functions are nested, this can become
  more complicated, so either a globel return value meaning table
  is needed or each function needs to convert error results of
  called functions (deleting some information).

0
Reply ram (2827) 1/28/2010 5:52:37 PM

Ertugrul =?UTF-8?B?U8O2eWxlbWV6?= <es@ertes.de> writes:
>Of course you can always write an interpreter for a richer language.
>That's not really 'doing it in C'.

  Yes, that was also my point.

  The assignment to �teach C� usually is /not/ fulfilled by
  teaching to create functions as

gmap(gmap(gmap(fun3(aLzy2(__1), aLzy(__1), __1), zs), ys), xs)

  although this is a part of a C program.

  But to teach C, one usually writes programs using only those
  concepts of the language that come �out of the box�, i.e.,
  are available from an (from every) implementation of C
  according to ISO/IEC 9899:1999 (E).

  For example, I would teach Linux system calls in C only iff
  the assignment is not �teach C�, but �teach Linux system
  programming in C�. However, I /do/ include some examples
  showing how third party libraries can be employed in own
  projects, but otherwise, I do not make the source code
  depending on them.

0
Reply ram (2827) 1/28/2010 6:01:56 PM

In article <1583434c-77e2-45b9-9229-6401e5567ea4@l30g2000yqb.googlegroups.com>, Nick Keighley <nick_keighley_nospam@hotmail.com> writes:

> if fclose() doesn't work why should fflush()?

It's not that fflush() should work. My point is that you're not done and
not ready to relinquish control to the RTS until you flush your buffered
writes, because flushing is when writing actually happens. Until that
point, you just declare your intent to write. If the RTS notices that
you have left some data buffered and it's unable to flush them, it has
no way to tell you.

Cheers,
lacos
0
Reply lacos (176) 1/28/2010 6:19:33 PM

On Jan 28, 5:35=A0pm, gwowen <gwo...@gmail.com> wrote:
> > Here's a quick example:
>
> > Now for the philosophical question: Where does The Matrix live?
> > - is it allocated by new and returned by reference?
>
> It behaves "as if" it were created as an "auto" and copied on
> assignment.
>
> > Who is supposed to clean it up?
>
> Whoever takes a copy cleans up their own copy.

Why? Wasn't it created "as if" it were an automatic variable? Why the
need to clean up after automatic variables? </
angstyfaceofnewbieterror>

> > Who manages the temporaries created by a+b+c ?
>
> RAII. =A0They're automatically destroyed once they're used.

Let's take a moment to think about that. I allocated a Matrix with
new. You said it behaves "as if" it were an automatic variable - why
would that be? Let's skip that question for a moment and let's think
about who destroys the Matrix; it must be someone who allocated it
with new, or someone that received a reference to it (explicitly
stated conventions notwithstanding etc.), because, as far as I can
tell, there is no automatic memory management in C++. Perhaps I am
missing something in your train of thought, though.
> > - is it returned by value?
>
> It is "as if" it is, yes.
>
> > Won't the copy constructor copy lots of matrices then?
>
> Only if the compiler cannot optimise the assignment away, while still
> behaving "as if" there were lots of copies. =A0Most compilers (even C
> compilers) don't return large structures on the stack or in registers,
> but use a hidden reference argument, so most compilers elide the
> copies. =A0 See RVO and NRVO.
> Of course, if you implement operator+=3D, you can elide those copies
> yourself.
>

> > Feel the madness. :-)
>
> Non-sequitor.

It'd be one if I were talking about crab ambulances. But, the pigeons
are still sleeping.


> > > > I mean, those are just a few. I've seen literally thousands of
> > > > complaints about the language constructs,
>
> Whoop-de-do. =A0I've seen literally thousands of complaints about almost
> everything. =A0People like complaining. =A0Can you name me a language
> about which vociferous angry people do not frequently complain?

Well, complaints usually arise when people with a certain mindset (for
instance, systems people) try to bring that mindset into other
contexts (for instance, web development). You know, the same people
that write C-like Perl. That aside, I've never heard a lot of
complaining about Python. Python enthusiasts seem to be just that -
enthusiastic.

> Not massively. =A0You're not obliged to use every feature of the
> language, and if you try to in C++, it will drive you insane. =A0If
> you're talking about doing heavily-templated-metaprogramming without
> understanding RVO, you might be trying to run before you can walk. But
> good design, a bit of care and a lot of restraint will see you through.

You are right in a certain degree. My pov is that you cannot do
heavily templated metaprogramming without running into severe language
restrictions (Understanding RVO? Really? Do I have to be familiar with
compiler optimizations to write correct code? Wow..), and in the end,
people use a small subset of C++ (which is a pity) and sleep well at
night. Those that will try to use the full power of the language (and
in theory it SHOULD be very powerful) will waste their time chasing
overload resolution ambiguities. I don't even care. :)
0
Reply electricdelta (73) 1/28/2010 6:35:58 PM

On 28 jan, 19:01, r...@zedat.fu-berlin.de (Stefan Ram) wrote:
> Ertugrul =3D?UTF-8?B?U8O2eWxlbWV6?=3D <e...@ertes.de> writes:
> >Of course you can always write an interpreter for a richer language.
> >That's not really 'doing it in C'.
>
> =A0 Yes, that was also my point.

There is a strong difference between an interpreter, a preprocessor
and an embedded DSL.

> =A0 The assignment to =BBteach C=AB usually is /not/ fulfilled by
> =A0 teaching to create functions as
>
> gmap(gmap(gmap(fun3(aLzy2(__1), aLzy(__1), __1), zs), ys), xs)
>
> =A0 although this is a part of a C program.

The statement was that closures cannot be built/used in C. I agree
that explaining the code above is beyond an advanced course on C, but
nevertheless it is possible in C.
0
Reply Laurent.Deniau (124) 1/28/2010 8:09:26 PM

Ian Collins <ian-news@hotmail.com> wrote:

> Michael Foukarakis wrote:
> > On Jan 26, 10:04 am, jacob navia <ja...@nospam.org> wrote:

> >> That could be done in C if we had operator overloading, something I have
> >> been trying to promote for years.
> > 
> > Operator overloading and lots of preprocessor tricks, correct?
> 
> Operator overloading and constructors/destructors, which are additions 
> that Jacob has vehemently opposed in the past.

No, we have always been at war with Eastasia.

Richard
0
Reply raltbos (821) 1/28/2010 8:24:54 PM

ld <laurent.deniau@gmail.com> writes:
>The statement was that closures cannot be built/used in C. I agree
>that explaining the code above is beyond an advanced course on C, but
>nevertheless it is possible in C.

  When given /only/ a C implementation, one needs a lot of
  effort to build such a library and then use it. One does not
  need this effort when using a language where these features
  are already part of the language. So, yes, it is possible in
  C, but might be more effort.

  You might say that one does not need to implement those
  features oneself, but can use a third-party library �L� for it.
  But then, the basis for development would not be �C�, but �C+L�.
  Nothing is wrong with using �C+L� as a basis, but it should 
  just not be called �C�, but �C+L�.

0
Reply ram (2827) 1/28/2010 8:46:14 PM

Nick <3-nospam@temporary-address.org.uk> wrote:

> Ertugrul S=C3=B6ylemez <es@ertes.de> writes:
>
> > The problem is not garbage collection.  It just makes it even more
> > complicated.  C is missing some very important high level control
> > constructs, most notably closures.  The only functional programming
> > you can do in C is continuation passing style, which is already an
> > improvement over the usual purely imperative style.  You get some
> > limited, but safe resource management that way.
> >
> > I have written an article about that, which you can find here:
> > <http://blog.ertes.de/2009/02/continuations-for-secure-code.html>.
> >
> > That article builds on the just-for-fun article, which started this
> > thread, and turns it into something actually useful.
>
> Commenting there is so painful (the comment editor embedded in the
> page doesn't recognise arrow keys!) I'll reply here instead!

As soon as my own blog software is up and running, I'll go away from
Blogger anyway, so I really prefer comments here.


> It's an interesting approach, and I can certainly see its value in a
> structure that requires a lot of specialised initialisation and
> destruction.  You could replace:
>
> struct foo *foop =3D Create_Foo_Structure();
> lots-and-lots-of-code-using foop
> Release_Foo_Structure(foop)
>
> with
>
> withFoo(dofoopstuff);
>
> but, of course, you have to create dofoopstuff(struct foo *foop)
> before you can do that, and in that case writing:
>
> struct foo *foop =3D Create_Foo_Structure();
> dofoopstuff(foop);
> Release_Foo_Structure(foop)
>
> does the same job, and you aren't likely to forget to release it when
> it's only two lines from creation.

That's a general problem of the way C programmers think.  Yes, if you
need it only once, you are faster just writing it out.  But the point
here is not efficiency, it's safety!  It's specifically that "you aren't
likely to forget" part of your reasoning, which is the big problem.
With that support function at hand, you _will not_ forget, and that's a
great advantage.


> And that's where I think this fails.  If this is the only benefit you
> get (in C obviously - I know some of the stuff you can do in a better
> framework) then it doesn't seem to give anything more than a
> programming discipline that says:
> - remove anything that uses an allocated structure (including a file
> pointer) into a separate function.
> - call the function immediately between allocation and release of the
> structures, and don't place /any/ other code in there.
>
> Still a neat idea, but I'm not convinced it normally has any practical
> value.

This is the only benefit, yes.  But it's not a small benefit.  It will
help make C code safer.  It's just that I'm afraid someone needs to drop
this into a somewhat large library.  Otherwise nobody will use it.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 1/30/2010 4:56:19 AM

Ertugrul Söylemez <es@ertes.de> writes:

> Nick <3-nospam@temporary-address.org.uk> wrote:
>
>> Ertugrul Söylemez <es@ertes.de> writes:
>>
>> > The problem is not garbage collection.  It just makes it even more
>> > complicated.  C is missing some very important high level control
>> > constructs, most notably closures.  The only functional programming
>> > you can do in C is continuation passing style, which is already an
>> > improvement over the usual purely imperative style.  You get some
>> > limited, but safe resource management that way.
>> >
>> > I have written an article about that, which you can find here:
>> > <http://blog.ertes.de/2009/02/continuations-for-secure-code.html>.
>> >
>> > That article builds on the just-for-fun article, which started this
>> > thread, and turns it into something actually useful.
>>
>> Commenting there is so painful (the comment editor embedded in the
>> page doesn't recognise arrow keys!) I'll reply here instead!
>
> As soon as my own blog software is up and running, I'll go away from
> Blogger anyway, so I really prefer comments here.
>
>
>> It's an interesting approach, and I can certainly see its value in a
>> structure that requires a lot of specialised initialisation and
>> destruction.  You could replace:
>>
>> struct foo *foop = Create_Foo_Structure();
>> lots-and-lots-of-code-using foop
>> Release_Foo_Structure(foop)
>>
>> with
>>
>> withFoo(dofoopstuff);
>>
>> but, of course, you have to create dofoopstuff(struct foo *foop)
>> before you can do that, and in that case writing:
>>
>> struct foo *foop = Create_Foo_Structure();
>> dofoopstuff(foop);
>> Release_Foo_Structure(foop)
>>
>> does the same job, and you aren't likely to forget to release it when
>> it's only two lines from creation.
>
> That's a general problem of the way C programmers think.  

Rather, I think, with the way people think when they are programming in
C.  Because of the way C works we are limited to just doing this.  

> Yes, if you
> need it only once, you are faster just writing it out.  But the point
> here is not efficiency, it's safety!  It's specifically that "you aren't
> likely to forget" part of your reasoning, which is the big problem.
> With that support function at hand, you _will not_ forget, and that's a
> great advantage.

In this discussion I'm not actually that bothered about efficiency -
either in terms of programmer effort or execution.  I'm more bothered
about benefits traded off against drawbacks.

To me, there's a big drawback here in that you end up splitting what may
well conceptually be a single piece of code into multiple functions.  If
you could stick literal functions in the call, for example, you could
put three line sequences that need a file pointer inside the "with
pointer" call.  But in C you can't.

So you are going to end up with your logical block of code scattered
into lots of little bits.

That to me seems a big drawback.  You say - correctly - that you are
less likely to forget to free the resource.  I sort of agree, but - in
my C programming experience - you tend to forget to release the resource
(or, far worse, release it twice) when you have the code all in one
block.
>
>> And that's where I think this fails.  If this is the only benefit you
>> get (in C obviously - I know some of the stuff you can do in a better
>> framework) then it doesn't seem to give anything more than a
>> programming discipline that says:
>> - remove anything that uses an allocated structure (including a file
>> pointer) into a separate function.
>> - call the function immediately between allocation and release of the
>> structures, and don't place /any/ other code in there.
>>
>> Still a neat idea, but I'm not convinced it normally has any practical
>> value.
>
> This is the only benefit, yes.  But it's not a small benefit.  It will
> help make C code safer.  It's just that I'm afraid someone needs to drop
> this into a somewhat large library.  Otherwise nobody will use it.

And this is where I disagree.  Once you've done the breaking the code
into little nuggets then wrapping each with "acquire" and "release" is
going to be simple.  You really aren't going to forget to do that
sequence, or put two releases in there.  So the rather clumsy syntax
gains you nothing.

I summary, I think that the limitations of C mean that this doesn't give
enough benefits.  But you've got me thinking about a hideous generic
"WITH_RESOURCE" macro that takes an acquire function, a function to
call, a release function, and a pile of arguments!
-- 
Online waterways route planner            | http://canalplan.eu
Plan trips, see photos, check facilities  | http://canalplan.org.uk
0
Reply 3-nospam (285) 1/30/2010 11:19:49 AM

Nick <3-nospam@temporary-address.org.uk> wrote:

> > Yes, if you need it only once, you are faster just writing it out.
> > But the point here is not efficiency, it's safety!  It's
> > specifically that "you aren't likely to forget" part of your
> > reasoning, which is the big problem.  With that support function at
> > hand, you _will not_ forget, and that's a great advantage.
>
> In this discussion I'm not actually that bothered about efficiency -
> either in terms of programmer effort or execution.  I'm more bothered
> about benefits traded off against drawbacks.
>
> To me, there's a big drawback here in that you end up splitting what
> may well conceptually be a single piece of code into multiple
> functions.  If you could stick literal functions in the call, for
> example, you could put three line sequences that need a file pointer
> inside the "with pointer" call.  But in C you can't.
>
> So you are going to end up with your logical block of code scattered
> into lots of little bits.
>
> That to me seems a big drawback.  You say - correctly - that you are
> less likely to forget to free the resource.  I sort of agree, but - in
> my C programming experience - you tend to forget to release the
> resource (or, far worse, release it twice) when you have the code all
> in one block.

Indeed, there is little syntactic support, but ...


> >> And that's where I think this fails.  If this is the only benefit
> >> you get (in C obviously - I know some of the stuff you can do in a
> >> better framework) then it doesn't seem to give anything more than a
> >> programming discipline that says:  - remove anything that uses an
> >> allocated structure (including a file pointer) into a separate
> >> function.  - call the function immediately between allocation and
> >> release of the structures, and don't place /any/ other code in
> >> there.
> >>
> >> Still a neat idea, but I'm not convinced it normally has any
> >> practical value.
> >
> > This is the only benefit, yes.  But it's not a small benefit.  It
> > will help make C code safer.  It's just that I'm afraid someone
> > needs to drop this into a somewhat large library.  Otherwise nobody
> > will use it.
>
> And this is where I disagree.  Once you've done the breaking the code
> into little nuggets then wrapping each with "acquire" and "release" is
> going to be simple.  You really aren't going to forget to do that
> sequence, or put two releases in there.  So the rather clumsy syntax
> gains you nothing.
>
> I summary, I think that the limitations of C mean that this doesn't
> give enough benefits.  But you've got me thinking about a hideous
> generic "WITH_RESOURCE" macro that takes an acquire function, a
> function to call, a release function, and a pile of arguments!

.... that idea is actually great.  Yes, a macro should work very well
here.  I haven't thought of that.


Greets
Ertugrul


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://blog.ertes.de/

0
Reply es1 (159) 1/31/2010 11:02:12 AM

ram@zedat.fu-berlin.de (Stefan Ram) writes:

> Paul Rubin <no.email@nospam.invalid> writes:
>>Well sure, but such sharing would be discovered by a tracing gc.
>
>   Yes, the whole point of my post is that C usually does
>   /not have/ a GC. So I infer that functional programming,
>   therefore, is difficult or nearly impossible (beyond a
>   certain level of complexity) in C.

When the Lisp Machines had only a few megaconses of memory, if not half
a megacons, I've been told they could run for a week without needing a
garbage collection, and people just rebooted them once a week to avoid
it.

Well, next month I'll buy a PC, a PERSONAL computer with 24 GB ram, or
3 Gconses.  I guess it could run without a garbage collection for a
month!

Perhaps today, for short lived C processes, you just don't have to care
about free anymore.  Just malloc, and exit.


-- 
__Pascal Bourguignon__
http://www.informatimago.com
0
Reply pjb (7646) 2/14/2010 2:55:41 PM

pjb@informatimago.com (Pascal J. Bourguignon) wrote:

> ram@zedat.fu-berlin.de (Stefan Ram) writes:
>
> > Paul Rubin <no.email@nospam.invalid> writes:
> >>Well sure, but such sharing would be discovered by a tracing gc.
> >
> >   Yes, the whole point of my post is that C usually does /not have/
> >   a GC. So I infer that functional programming, therefore, is
> >   difficult or nearly impossible (beyond a certain level of
> >   complexity) in C.
>
> When the Lisp Machines had only a few megaconses of memory, if not
> half a megacons, I've been told they could run for a week without
> needing a garbage collection, and people just rebooted them once a
> week to avoid it.
>
> Well, next month I'll buy a PC, a PERSONAL computer with 24 GB ram, or
> 3 Gconses.  I guess it could run without a garbage collection for a
> month!
>
> Perhaps today, for short lived C processes, you just don't have to
> care about free anymore.  Just malloc, and exit.

This reasoning is used by many PHP programmers today.  It's one reason
why PHP programs are so error-prone and why PHP errors are often hard to
find.  There is no excuse for unfreed resources, particularly in
languages, which are unsafe by nature, like C and PHP.  It _will_ get
you into trouble sooner or later.

Note that in both C and PHP most results are computed solely through
side-effects and are never obtained in a direct fashion.  It is very
important that you get these side effects under control, even if your
process is short-lived.  My proposal is one way of doing this.

The better way is to avoid using side effects altogether, but that's
close to impossible in C (and PHP).


Greets
Ertugrul


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/14/2010 11:22:32 PM

Pascal J. Bourguignon wrote:

<snip>

> Perhaps today, for short lived C processes, you just don't have to care
> about free anymore.  Just malloc, and exit.

Perhaps that's the reasoning used by the Firefox guys. When running 
Win32, I choose Firefox rather than IE, but that's becoming a harder 
decision than it should be. The other day, I peeked at Task Manager and 
found that Firefox (which I rarely leave running for long because I know 
it's a hog) had grabbed well over half a gigabyte of memory. I rarely 
have more than one window open, and rarely more than one (perhaps two or 
three, and very occasionally up to a dozen) tabs in that window. Half a 
gigabyte. It's just ludicrous. And it slows everything else down, 
because less available RAM means more swapping, and more swapping means 
more disk access.

Stupid stupid stupid. Don't follow their bad example. Write code 
properly. *Please*.

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 2/15/2010 7:25:46 AM

Richard Heathfield wrote:
> Pascal J. Bourguignon wrote:
>
> <snip>
>
> > Perhaps today, for short lived C processes, you just don't have to care
> > about free anymore.  Just malloc, and exit.
>
> Perhaps that's the reasoning used by the Firefox guys. When running
> Win32, I choose Firefox rather than IE, but that's becoming a harder
> decision than it should be. The other day, I peeked at Task Manager and
> found that Firefox (which I rarely leave running for long because I know
> it's a hog) had grabbed well over half a gigabyte of memory. I rarely
> have more than one window open, and rarely more than one (perhaps two or
> three, and very occasionally up to a dozen) tabs in that window. Half a
> gigabyte. It's just ludicrous.

Are you sure that's physical memory? During normal use (similar to
what you describe), Firefox does grab over 500 megabytes of virtual
memory, but usually only about a couple of hundred Mb of physical
memory. Atleast, that's the usage pattern for me here. And I'm running
Linux, but I suspect memory usage is quite similar in Windows too.

> And it slows everything else down,
> because less available RAM means more swapping, and more swapping means
> more disk access.

I notice though that all popular graphical browsers have roughly
comparable memory consumption. Certainly, in my experience, Firefox,
SeaMonkey, Galeon, Chrome. Opera tends to consume about 50 Mb less
than these.

> Stupid stupid stupid. Don't follow their bad example. Write code
> properly. *Please*.

I wouldn't single out Firefox though. The fact that all major
graphical browsers consume roughly similar amounts of memory for
similar use seems to show that either there's a good reason or that
fine grained resource management gets unmanageably complicated in very
large software projects.

It'd be interesting to see what difference a garbage collector does to
a program like Firefox (assuming it doesn't already have one inside.)
It would give us a clue as to whether the memory hogging is due to
tangible requirements or just accumulation of expired objects.
0
Reply santosh.k83 (3969) 2/15/2010 7:57:58 AM

santosh wrote:
> Richard Heathfield wrote:

<snip>

>> Half a gigabyte. It's just ludicrous.
> 
> Are you sure that's physical memory?

Well, of course your asking the question makes me doubt the answer, and 
I lack the time to check in more detail right now, BUT...

 > During normal use (similar to
> what you describe), Firefox does grab over 500 megabytes of virtual
> memory, but usually only about a couple of hundred Mb of physical
> memory.

*ONLY* a couple of hundred megabytes? Can you hear yourself? :-)

> Atleast, that's the usage pattern for me here. And I'm running
> Linux,

Likewise. I actually use both OSs (on different machines).

<snip>

> I notice though that all popular graphical browsers have roughly
> comparable memory consumption. Certainly, in my experience, Firefox,
> SeaMonkey, Galeon, Chrome. Opera tends to consume about 50 Mb less
> than these.

Yes, but they're only Web browsers. They're not supposed to hold the 
entire Internet in RAM!

>> Stupid stupid stupid. Don't follow their bad example. Write code
>> properly. *Please*.
> 
> I wouldn't single out Firefox though. The fact that all major
> graphical browsers consume roughly similar amounts of memory for
> similar use seems to show that either there's a good reason or that
> fine grained resource management gets unmanageably complicated in very
> large software projects.

It'd be nice if someone with too much time on their hands could write a 
"lite" Web browser that guarantees never to use more than, say, 64MB of 
memory. If that means some hard decisions on feature selection, so be it.

(There is a Linux distro - I think it's "Puppy" BICBW - that restricts 
itself to no more than 50MB of disk space. Not the same thing as RAM, 
obviously, but it's a similar idea.)

<snip>

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 2/15/2010 9:15:15 AM

In article <7ybpfrzx1v.fsf@informatimago.com>, pjb@informatimago.com (Pascal J. Bourguignon) writes:

> Perhaps today, for short lived C processes, you just don't have to care
> about free anymore.  Just malloc, and exit.

That seems to be a bit negligent even for programs that allocate memory
frugally; for me it encourages a style where you don't know something
about your program's state that you should know in general.

And of course there are short lived C programs that are a bit hungry.
I've just repeated a 64-bit decompression test on the NIIFI's computer,
described under [0], with 55 worker threads. (The input file is
8,457,341,456 bytes big.) lbzip2 ran for 1 minute and 34.81 seconds, so
it could reasonably be called a short lived process. Its peak allocation
was 1,349,156,524 bytes. Its *cumulative* allocation was 178,286,146,620
bytes.

Cheers,
lacos

[0] http://lacos.hu/lbzip2-scaling/scaling.html
0
Reply lacos (176) 2/15/2010 11:21:27 AM

In article <fdd6608e-899e-498b-b081-2261b170b34d@u15g2000prd.googlegroups.com>, santosh <santosh.k83@gmail.com> writes:
> Richard Heathfield wrote:
>> Pascal J. Bourguignon wrote:
>>
>> <snip>
>>
>> > Perhaps today, for short lived C processes, you just don't have to care
>> > about free anymore.  Just malloc, and exit.
>>
>> Perhaps that's the reasoning used by the Firefox guys. When running
>> Win32, I choose Firefox rather than IE, but that's becoming a harder
>> decision than it should be. The other day, I peeked at Task Manager and
>> found that Firefox (which I rarely leave running for long because I know
>> it's a hog) had grabbed well over half a gigabyte of memory. I rarely
>> have more than one window open, and rarely more than one (perhaps two or
>> three, and very occasionally up to a dozen) tabs in that window. Half a
>> gigabyte. It's just ludicrous.
> 
> Are you sure that's physical memory?

It better be. I configure my system that way.


> During normal use (similar to
> what you describe), Firefox does grab over 500 megabytes of virtual
> memory, but usually only about a couple of hundred Mb of physical
> memory.

And that's an invitation for a stab in the back by the OOM killer.
Rather waste sincerely and honestly than speculate.


>> And it slows everything else down,
>> because less available RAM means more swapping, and more swapping means
>> more disk access.

(Yes, I know this was written by Richard.) Semi-modern workstations
should run without swap, in my opinion; "a few G or RAM should be enough
for everyone" :) Really, suppose you have 2G RAM, and some processes
spill over into swap. The random-like memory access patterns of several
processes are now reflected by the head movements of your consumer-grade
hard disk. (The I/O scheduler, if any, can help only so much.) You won't
be able to bring up a terminal or task manager to find / suspend / kill
the offender(s) in reasonable time.

In a desktop situation where swap would help, swap is no help. Most of
the time I like a clean and quick "out of memory, exiting" message more
than waiting for several minutes on the disk (and probably getting the
same message in the end).

I have no experience with solid-state drives, but consumer-grade thumb
drives etc have *catastrophic* random-write performance, especially the
bigger ones -- they are worse for swapping than traditional hard disks.


> I notice though that all popular graphical browsers have roughly
> comparable memory consumption. Certainly, in my experience, Firefox,
> SeaMonkey, Galeon, Chrome. Opera tends to consume about 50 Mb less
> than these.

I suppose browsers have to handle lots and lots of small objects, ie.
objects that don't deserve their own mmap()-ed pages in the default
malloc configuration. This likely leads to hellish heap fragmentation
and a huge heap VMA. It would be interesting to see how memory usage is
affected after a long browsing session, when one opens a pristine
window, closes everything else, stops all downloads, and clears all
history and caches. In that case, even the heap VMA should be trimmed.

Cheers,
lacos
0
Reply lacos (176) 2/15/2010 2:09:49 PM

On Mon, 15 Feb 2010 15:09:49 +0100, Ersek, Laszlo wrote:

>>> And it slows everything else down,
>>> because less available RAM means more swapping, and more swapping means
>>> more disk access.
> 
> (Yes, I know this was written by Richard.) Semi-modern workstations should
> run without swap, in my opinion;

You should have enough swap for things which should get swapped out and
(normally) stay swapped out.

Many programs initialise a lot of data at startup then never touch it
again unless you use that particular feature. There's no point having such
data locked into RAM when there are better ways to use it.

Similarly, modern desktop systems tend to run a lot of programs which are
"running" for as long as you're logged in but seldom see actual use.

0
Reply nobody (4805) 2/15/2010 3:55:26 PM

Richard Heathfield wrote:
) santosh wrote:
)> Are you sure that's physical memory?
)
) Well, of course your asking the question makes me doubt the answer, and 
) I lack the time to check in more detail right now, BUT...
)
) > During normal use (similar to
)> what you describe), Firefox does grab over 500 megabytes of virtual
)> memory, but usually only about a couple of hundred Mb of physical
)> memory.
)
) *ONLY* a couple of hundred megabytes? Can you hear yourself? :-)

<snip>

Isn't that just the in-memory cache though ?
Could very well even be a config option.


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply willem7123 (117) 2/15/2010 5:43:00 PM

On 2010-02-15, Willem <willem@snail.stack.nl> wrote:
> Richard Heathfield wrote:
> ) santosh wrote:
> )> Are you sure that's physical memory?
> )
> ) Well, of course your asking the question makes me doubt the answer, and 
> ) I lack the time to check in more detail right now, BUT...
> )
> ) > During normal use (similar to
> )> what you describe), Firefox does grab over 500 megabytes of virtual
> )> memory, but usually only about a couple of hundred Mb of physical
> )> memory.
> )
> ) *ONLY* a couple of hundred megabytes? Can you hear yourself? :-)
>
><snip>
>
> Isn't that just the in-memory cache though ?
> Could very well even be a config option.
>

That might explain why it also takes ten seconds to load, while
Opera takes four and Chrome just over one.

IME since 2.1 (IIRC) Firefox has been progressively slower and
bloatier. The latest version was a slight uptick, but not much.

>
> SaSW, Willem

0
Reply apoelstra (387) 2/15/2010 6:19:37 PM

Nobody <nobody@nowhere.com> writes:
> Many programs initialise a lot of data at startup then never touch it
> again unless you use that particular feature. There's no point having such
> data locked into RAM when there are better ways to use it.
>
> Similarly, modern desktop systems tend to run a lot of programs which are
> "running" for as long as you're logged in but seldom see actual use.

Hey, don't forget about mobile phones - they do that too!

And your two paragraphs are linked. Because there's so much 
unnecessary crap happening at program startup, one can no 
longer afford to start them on demand - they need to be pre-
started. Which means that they have to hang around while you're
not using them.

Phil
-- 
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
0
Reply thefatphil_demunged (1558) 2/16/2010 9:42:37 AM

On 2/14/2010 6:22 PM, Ertugrul S�ylemez wrote:
> pjb@informatimago.com (Pascal J. Bourguignon) wrote:
>> Perhaps today, for short lived C processes, you just don't have to
>> care about free anymore.  Just malloc, and exit.
>
> This reasoning is used by many PHP programmers today.  It's one reason
> why PHP programs are so error-prone and why PHP errors are often hard to
> find.  There is no excuse for unfreed resources, particularly in
> languages, which are unsafe by nature, like C and PHP.  It _will_ get
> you into trouble sooner or later.

There is generally no need to free resources just before
program exit, because the operating system will do that
for you - a program which spends a bunch of time freeing
every allocated object and then exits has just wasted all
of that time. It's important to free resources which can
be allocated in an unbounded fashion. That is, a program
should act like a garbage collector - unreachable objects
must be reclaimed, but reachable ones don't need to be.
0
Reply hyrosen (1792) 2/16/2010 3:29:12 PM

On 2010-02-16, Hyman Rosen <hyrosen@mail.com> wrote:
> On 2/14/2010 6:22 PM, Ertugrul S�ylemez wrote:
>> pjb@informatimago.com (Pascal J. Bourguignon) wrote:
>>> Perhaps today, for short lived C processes, you just don't have to
>>> care about free anymore.  Just malloc, and exit.
>>
>> This reasoning is used by many PHP programmers today.  It's one reason
>> why PHP programs are so error-prone and why PHP errors are often hard to
>> find.  There is no excuse for unfreed resources, particularly in
>> languages, which are unsafe by nature, like C and PHP.  It _will_ get
>> you into trouble sooner or later.
>
> There is generally no need to free resources just before
> program exit, because the operating system will do that

What basis do you have for this absurd claim...

> for you - a program which spends a bunch of time freeing
> every allocated object and then exits has just wasted all

....or this one? The OS, if it frees your memory, needs just
as much CPU time as your code would, had you chosen to make
it portable to machines who are not your mother.

> of that time. It's important to free resources which can
> be allocated in an unbounded fashion. That is, a program
> should act like a garbage collector - unreachable objects
> must be reclaimed, but reachable ones don't need to be.

0
Reply apoelstra (387) 2/16/2010 3:45:49 PM

On 2/16/2010 10:45 AM, Andrew Poelstra wrote:
> On 2010-02-16, Hyman Rosen<hyrosen@mail.com>  wrote:
>> There is generally no need to free resources just before
>> program exit, because the operating system will do that
>
> What basis do you have for this absurd claim...

Experience. Logic.

>> for you - a program which spends a bunch of time freeing
>> every allocated object and then exits has just wasted all
>
> ...or this one? The OS, if it frees your memory, needs just
> as much CPU time as your code would, had you chosen to make
> it portable to machines who are not your mother.

No. A program which insists on freeing its allocated memory
does so by going through each allocated object individually
freeing it. This can involve large amounts of time when the
program has allocated millions of objects in its data
structures. Upon program exit, the operating system reclaims
all memory allocated by the program in one action, and that
takes essentially no time at all.

This is not even to mention that when a program frees allocated
memory through 'free', it is usually doing nothing but placing
that memory back onto an internal data structure so that it may
be allocated again. It is seldom returned to the operating system
because it was not allocated that way; allocators request large
blocks and break them up internally to the program.
0
Reply hyrosen (1792) 2/16/2010 3:57:17 PM

On Feb 16, 10:45=A0am, Andrew Poelstra <apoels...@localhost.localdomain>
wrote:
> On 2010-02-16, Hyman Rosen <hyro...@mail.com> wrote:
>
> > On 2/14/2010 6:22 PM, Ertugrul S=F6ylemez wrote:
> >> p...@informatimago.com (Pascal J. Bourguignon) wrote:
> >>> Perhaps today, for short lived C processes, you just don't have to
> >>> care about free anymore. =A0Just malloc, and exit.
>
> >> This reasoning is used by many PHP programmers today. =A0It's one reas=
on
> >> why PHP programs are so error-prone and why PHP errors are often hard =
to
> >> find. =A0There is no excuse for unfreed resources, particularly in
> >> languages, which are unsafe by nature, like C and PHP. =A0It _will_ ge=
t
> >> you into trouble sooner or later.
>
> > There is generally no need to free resources just before
> > program exit, because the operating system will do that
>
> What basis do you have for this absurd claim...
>
> > for you - a program which spends a bunch of time freeing
> > every allocated object and then exits has just wasted all
>
> ...or this one? The OS, if it frees your memory, needs just
> as much CPU time as your code would,

AFAICT Hyman is correctly pointing out that meticulous free'ing of
individual allocations is potentially expensive and pointless
maintenance, if the process is terminating. The operating system does
not do the equivalent free'ing operations, but rather, the heap just
goes away, at no cost.

> had you chosen to make
> it portable to machines who are not your mother.
>
>
>
> > of that time. It's important to free resources which can
> > be allocated in an unbounded fashion. That is, a program
> > should act like a garbage collector - unreachable objects
> > must be reclaimed, but reachable ones don't need to be.

0
Reply toby23 (1080) 2/16/2010 3:57:39 PM

"Andrew Poelstra" <apoelstra@localhost.localdomain> ha scritto nel messaggio 
news:slrnhnlfa4.6sc.apoelstra@localhost.localdomain...
> On 2010-02-16, Hyman Rosen <hyrosen@mail.com> wrote:
>> On 2/14/2010 6:22 PM, Ertugrul S�ylemez wrote:
>>> pjb@informatimago.com (Pascal J. Bourguignon) wrote:
>>>> Perhaps today, for short lived C processes, you just don't have to
>>>> care about free anymore.  Just malloc, and exit.
>>>
>>> This reasoning is used by many PHP programmers today.  It's one reason
>>> why PHP programs are so error-prone and why PHP errors are often hard to
>>> find.  There is no excuse for unfreed resources, particularly in
>>> languages, which are unsafe by nature, like C and PHP.  It _will_ get
>>> you into trouble sooner or later.
>>
>> There is generally no need to free resources just before
>> program exit, because the operating system will do that
>
> What basis do you have for this absurd claim...
>
>> for you - a program which spends a bunch of time freeing
>> every allocated object and then exits has just wasted all
>
> ...or this one? The OS, if it frees your memory, needs just
> as much CPU time as your code would,

this should be wrong, bacause OS should free
all big arrays of chars
that give to the malloc function (heap) instead you
have to free all the sub arrays of these big arrays

> had you chosen to make
> it portable to machines who are not your mother.
>
>> of that time. It's important to free resources which can
>> be allocated in an unbounded fashion. That is, a program
>> should act like a garbage collector - unreachable objects
>> must be reclaimed, but reachable ones don't need to be.
> 


0
Reply io_x 2/16/2010 4:00:17 PM

On 2010-02-16, Hyman Rosen <hyrosen@mail.com> wrote:
> On 2/16/2010 10:45 AM, Andrew Poelstra wrote:
>> On 2010-02-16, Hyman Rosen<hyrosen@mail.com>  wrote:
>>> There is generally no need to free resources just before
>>> program exit, because the operating system will do that
>>
>> What basis do you have for this absurd claim...
>
> Experience. Logic.
>

Experience, perhaps, if your experience is truly that limited.

Logic, no.

>>> for you - a program which spends a bunch of time freeing
>>> every allocated object and then exits has just wasted all
>>
>> ...or this one? The OS, if it frees your memory, needs just
>> as much CPU time as your code would, had you chosen to make
>> it portable to machines who are not your mother.
>
> No. A program which insists on freeing its allocated memory
> does so by going through each allocated object individually
> freeing it. This can involve large amounts of time when the
> program has allocated millions of objects in its data
> structures. Upon program exit, the operating system reclaims
> all memory allocated by the program in one action, and that
> takes essentially no time at all.
>

Perhaps you should write memory managers, if you can really
reclaim millions of individually allocated blocks in a single
action. (Though given your belief there is no need to do so,
I have an idea of how it might work...)

> This is not even to mention that when a program frees allocated
> memory through 'free', it is usually doing nothing but placing
> that memory back onto an internal data structure so that it may
> be allocated again. It is seldom returned to the operating system
> because it was not allocated that way; allocators request large
> blocks and break them up internally to the program.

Allocators allocate. To ascribe anything more to them is
presumptuous and unjustified.


0
Reply apoelstra (387) 2/16/2010 4:25:06 PM

On 2010-02-16, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> ...or this one? The OS, if it frees your memory, needs just
> as much CPU time as your code would, had you chosen to make
> it portable to machines who are not your mother.

Not generally true.

Imagine that I have allocated a linked list of a million nodes, each
pointing to 1024 bytes of data.  On a typical malloc implementation,
freeing these will result in no fewer than two million separate operations,
each of which may also result in complicated operations as the library
consolidates free space, etcetera.

The operating system will simply mark my pages unused -- which it has to do
whether or not I've freed them in terms of the library operation.

The operating system can do it faster because it doesn't need to care about
the internals and bookkeeping of the malloc arena.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 5:09:02 PM

On 2010-02-16, Seebs <usenet-nospam@seebs.net> wrote:
> On 2010-02-16, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
>> ...or this one? The OS, if it frees your memory, needs just
>> as much CPU time as your code would, had you chosen to make
>> it portable to machines who are not your mother.
>
> Not generally true.
>
> Imagine that I have allocated a linked list of a million nodes, each
> pointing to 1024 bytes of data.  On a typical malloc implementation,
> freeing these will result in no fewer than two million separate operations,
> each of which may also result in complicated operations as the library
> consolidates free space, etcetera.
>
> The operating system will simply mark my pages unused -- which it has to do
> whether or not I've freed them in terms of the library operation.
>
> The operating system can do it faster because it doesn't need to care about
> the internals and bookkeeping of the malloc arena.
>

But you would need to have found a gigabyte of contiguous memory
dedicated to your program for this to be simple - otherwise you
would be in memory space also used by other applications, and
bookkeeping does matter.

0
Reply apoelstra (387) 2/16/2010 5:18:14 PM

On 2010-02-16, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> But you would need to have found a gigabyte of contiguous memory
> dedicated to your program for this to be simple - otherwise you
> would be in memory space also used by other applications, and
> bookkeeping does matter.

It's rather more complicated on most systems.  But, in general, there is
nothing you can do inside the program that will reduce the total amount of
bookkeeping that needs to be done on exit, and simply not freeing anything
(as in free()) does not increase the amount of bookkeeping that needs to be
done.

The closest you could get is that some implementations may be such that,
once you've freed all the storage allocated within a given block of
OS-provided storage, you can return that block to the OS, meaning that it does
the bookkeeping to free that block right away, rather than having to do it
after you exit, but this can't make things any *better*, and may make things
*worse*.  (For instance, if you end up releasing a block between two other
blocks -- the OS might have to do extra work there that it wouldn't if all
three were released at once.)

Note that "contiguous" is pretty much irrelevant on most modern systems,
as program address spaces are all virtual anyway.

So the fact remains:  In general, on all the major platforms in use, there is
no possible case where calling free() a lot right before termination can make
things any better, and there are many obvious cases where they can make things
worse by orders of magnitude.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 5:30:29 PM

Andrew Poelstra a �crit :
> On 2010-02-16, Hyman Rosen <hyrosen@mail.com> wrote:
>> On 2/14/2010 6:22 PM, Ertugrul S�ylemez wrote:
>>> pjb@informatimago.com (Pascal J. Bourguignon) wrote:
>>>> Perhaps today, for short lived C processes, you just don't have to
>>>> care about free anymore.  Just malloc, and exit.
>>> This reasoning is used by many PHP programmers today.  It's one reason
>>> why PHP programs are so error-prone and why PHP errors are often hard to
>>> find.  There is no excuse for unfreed resources, particularly in
>>> languages, which are unsafe by nature, like C and PHP.  It _will_ get
>>> you into trouble sooner or later.
>> There is generally no need to free resources just before
>> program exit, because the operating system will do that
> 
> What basis do you have for this absurd claim...


"Absurd claim"

ALL OS do that. If not, they would run a single leaking program and 
would die immediately.

I have never seen an OS that did not do that.
> 
>> for you - a program which spends a bunch of time freeing
>> every allocated object and then exits has just wasted all
> 
> ...or this one? The OS, if it frees your memory, needs just
> as much CPU time as your code would, 

No, in most cases it will use a single free() call
since all memory allocated for a process will be in
a single heap.

> had you chosen to make
> it portable to machines who are not your mother.
> 

Nonsense

0
Reply jacob31 (869) 2/16/2010 5:38:40 PM

On 2010-02-16, jacob navia <jacob@spamsink.net> wrote:
> Andrew Poelstra a �crit :
>> On 2010-02-16, Hyman Rosen <hyrosen@mail.com> wrote:
>>> On 2/14/2010 6:22 PM, Ertugrul S�ylemez wrote:
>>>> pjb@informatimago.com (Pascal J. Bourguignon) wrote:
>>>>> Perhaps today, for short lived C processes, you just don't have to
>>>>> care about free anymore.  Just malloc, and exit.
>>>> This reasoning is used by many PHP programmers today.  It's one reason
>>>> why PHP programs are so error-prone and why PHP errors are often hard to
>>>> find.  There is no excuse for unfreed resources, particularly in
>>>> languages, which are unsafe by nature, like C and PHP.  It _will_ get
>>>> you into trouble sooner or later.
>>> There is generally no need to free resources just before
>>> program exit, because the operating system will do that
>> 
>> What basis do you have for this absurd claim...
>
>
> "Absurd claim"
>
> ALL OS do that. If not, they would run a single leaking program and 
> would die immediately.
>

Not immediately. And if this was an embedded system, eventually
the watchdog would kick and the programmer would (hopefully)
realize that his code was buggy and needed fixing.

> I have never seen an OS that did not do that.

Again, in embedded systems many OS's choose not to support
bad programming. There are no users downloading garbage
from the Internet and blithely expecting it to run despite
barely being compilable.

>> 
>>> for you - a program which spends a bunch of time freeing
>>> every allocated object and then exits has just wasted all
>> 
>> ...or this one? The OS, if it frees your memory, needs just
>> as much CPU time as your code would, 
>
> No, in most cases it will use a single free() call
> since all memory allocated for a process will be in
> a single heap.
>

But in "most cases" there is so little memory allocated
that the equivalent free() calls will take practically
zero time anyway. In the cases that a ton of memory is
used, then the OS has its work set out for it whether or
not the code is explicitly calling free().

>> had you chosen to make
>> it portable to machines who are not your mother.
>> 

0
Reply apoelstra (387) 2/16/2010 5:51:25 PM

On 2010-02-16, jacob navia <jacob@spamsink.net> wrote:
> ALL OS do that. If not, they would run a single leaking program and 
> would die immediately.
>
> I have never seen an OS that did not do that.

Have you never seen Windows 3.1 or DOS?  Both had C implementations where
malloc() could reserve memory that lived past program termination.  I think
the Amiga did too.

I mean, not saying that it's still a major issue for most people.  But there
certainly did exist such machines, and some people may care about them.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 5:53:26 PM

On 2010-02-16, Seebs <usenet-nospam@seebs.net> wrote:
>
> So the fact remains:  In general, on all the major platforms in use, there is
> no possible case where calling free() a lot right before termination can make
> things any better, and there are many obvious cases where they can make things
> worse by orders of magnitude.
>

Leaving aside OS's that do not or cannot cleanup, because to the
best of my knowledge no "big" OS's are in use that are like that:


I am going to disagree with you on this point: on my system, if a program
cleans up its own memory, I see a delay between clicking the X (or Ctrl+C,
or whatever) and the program actually dying. During this time it does its
cleanup, plays with the hard drive and whatever. Meanwhile, I am free to
do other things.

However, if the program just dies, I see a quick and painless exit. And
then the kernel takes over to do cleanup, which has a higher priority than
the dead program. And while it's cleaning up, the rest of my system is
sluggish, even if only for a second.

Better the cleanup be done with the program's CPU slices than my UI's,
I say.


Andrew

0
Reply apoelstra (387) 2/16/2010 6:06:42 PM

Hyman Rosen <hyrosen@mail.com> wrote:

> On 2/14/2010 6:22 PM, Ertugrul S=C3=B6ylemez wrote:
> > pjb@informatimago.com (Pascal J. Bourguignon) wrote:
> >> Perhaps today, for short lived C processes, you just don't have to
> >> care about free anymore.  Just malloc, and exit.
> >
> > This reasoning is used by many PHP programmers today.  It's one
> > reason why PHP programs are so error-prone and why PHP errors are
> > often hard to find.  There is no excuse for unfreed resources,
> > particularly in languages, which are unsafe by nature, like C and
> > PHP.  It _will_ get you into trouble sooner or later.
>
> There is generally no need to free resources just before program exit,
> because the operating system will do that for you - a program which
> spends a bunch of time freeing every allocated object and then exits
> has just wasted all of that time. It's important to free resources
> which can be allocated in an unbounded fashion. That is, a program
> should act like a garbage collector - unreachable objects must be
> reclaimed, but reachable ones don't need to be.

Okay, first let's talk about C.  In C memory allocation and freeing is
not quite fast, so you're indeed making a good point.  There is also no
garbage collector, which does that job for you.  However, there is still
a very important reason to free your memory.  At some point in time you
may want to restructure your program, perhaps to enhance it, at which
point it will get you into trouble.  We're talking about safety and
modularity here.

Next thing is that exiting a program, which really allocates millions of
memory blocks generally doesn't need to exit that fast anyway.  Also
note that allocating and freeing 5 million (!) blocks of 256 bytes using
malloc/free takes only around 1.6 seconds here (Athlon64 x2 with 2.7 GHz
and 2 GiB of RAM).  The program I used can be found at [1].

So still there is no excuse for not freeing memory.  And that's just
about memory, but I was talking about all kinds of resources.  Not
freeing them will get you into trouble.  If you're too convinced (or
lazy) to do it, better stop using C.  You're writing unsafe, nonmodular
code, because of conviction (or laziness).

Now let's talk about PHP, which is a garbage-collected language, so you
don't deal with memory anyway, unless you specifically want to (e.g. by
using unset()).  But there are a lot of resource types, which are not
covered by the garbage collector like files and database connections.
You should free them for the same reasons as above.  You're not doing
anything the PHP runtime wouldn't do by itself, but you're writing safe,
modular code that way, which is hardly slower.

[1] http://codepad.org/tjlVGJB8


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/16/2010 6:10:13 PM

On 2010-02-16, Ertugrul S�ylemez <es@ertes.de> wrote:
> So still there is no excuse for not freeing memory.

Again, there are a couple.  However, they're usually system-specific.  I can
point you at an obvious case, although it's not portable:  If you wish to
execute another program in a UNIX-like environment, you almost certainly
need to allocate the space for its argument list... And then your program
exits to exec the other program.  You must not free the memory before
calling exec(), and after exec(), you don't exist.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 6:20:51 PM

On 2010-02-16, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> I am going to disagree with you on this point: on my system, if a program
> cleans up its own memory, I see a delay between clicking the X (or Ctrl+C,
> or whatever) and the program actually dying. During this time it does its
> cleanup, plays with the hard drive and whatever. Meanwhile, I am free to
> do other things.

Yes.

> However, if the program just dies, I see a quick and painless exit. And
> then the kernel takes over to do cleanup, which has a higher priority than
> the dead program. And while it's cleaning up, the rest of my system is
> sluggish, even if only for a second.

You are mistaken.

This gets pretty off-topic, but:  The OS is doing the same cleanup either way.
What can create a noticeable sluggishness is that, if something aborts,
the kernel may choose to dump core -- which is to say, *write out to disk*
a copy of the process memory space.  Which can slow things down quite a bit.

If you don't have coredumps, there's no extra cost.

Seriously, I have worked on this code.  The kernel does the same cleanup
either way, nothing the program does prior to exiting saves it any time in
most real-world cases.  Again, *the kernel does not know or care how the
process has divided up its memory*.  In most cases, the process has a single
huge block of memory (from the kernel's point of view), even if the process
has internally subdivided it into thousands or millions of chunks.  The
kernel cleanup is the same either way.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 6:23:12 PM

Seebs wrote:
) On 2010-02-16, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
)> I am going to disagree with you on this point: on my system, if a program
)> cleans up its own memory, I see a delay between clicking the X (or Ctrl+C,
)> or whatever) and the program actually dying. During this time it does its
)> cleanup, plays with the hard drive and whatever. Meanwhile, I am free to
)> do other things.
)
) Yes.
)
)> However, if the program just dies, I see a quick and painless exit. And
)> then the kernel takes over to do cleanup, which has a higher priority than
)> the dead program. And while it's cleaning up, the rest of my system is
)> sluggish, even if only for a second.
)
) You are mistaken.
)
) This gets pretty off-topic, but:  The OS is doing the same cleanup either way.
) What can create a noticeable sluggishness is that, if something aborts,
) the kernel may choose to dump core -- which is to say, *write out to disk*
) a copy of the process memory space.  Which can slow things down quite a bit.

That's pretty Unix-specific.
On windows, I guess something similar does happen, that the OS is trying to
do some kind of crash-recovery or writing debug info or reporting stuff or
whatever when a program terminates abnormally.  Perhaps there's even a
Dr.Watson or similar running in the background that does stack traces and
all kinds of error reporting whenever a program crashes.


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply willem7123 (117) 2/16/2010 6:49:55 PM

Andrew Poelstra a �crit :
> On 2010-02-16, jacob navia <jacob@spamsink.net> wrote:
>> Andrew Poelstra a �crit :
>>> On 2010-02-16, Hyman Rosen <hyrosen@mail.com> wrote:
>>>> On 2/14/2010 6:22 PM, Ertugrul S�ylemez wrote:
>>>>> pjb@informatimago.com (Pascal J. Bourguignon) wrote:
>>>>>> Perhaps today, for short lived C processes, you just don't have to
>>>>>> care about free anymore.  Just malloc, and exit.
>>>>> This reasoning is used by many PHP programmers today.  It's one reason
>>>>> why PHP programs are so error-prone and why PHP errors are often hard to
>>>>> find.  There is no excuse for unfreed resources, particularly in
>>>>> languages, which are unsafe by nature, like C and PHP.  It _will_ get
>>>>> you into trouble sooner or later.
>>>> There is generally no need to free resources just before
>>>> program exit, because the operating system will do that
>>> What basis do you have for this absurd claim...
>>
>> "Absurd claim"
>>
>> ALL OS do that. If not, they would run a single leaking program and 
>> would die immediately.
>>
> 
> Not immediately.

????

> And if this was an embedded system, eventually
> the watchdog would kick and the programmer would (hopefully)
> realize that his code was buggy and needed fixing.
>

the code is not buggy.


>> I have never seen an OS that did not do that.
> 
> Again, in embedded systems many OS's choose not to support
> bad programming. There are no users downloading garbage
> from the Internet and blithely expecting it to run despite
> barely being compilable.
> 

OK. In your pet os (with lowercase) a program that has
a memory leak will bring the whole system down.

GREAT SYSTEM!

>>>> for you - a program which spends a bunch of time freeing
>>>> every allocated object and then exits has just wasted all
>>> ...or this one? The OS, if it frees your memory, needs just
>>> as much CPU time as your code would, 
>> No, in most cases it will use a single free() call
>> since all memory allocated for a process will be in
>> a single heap.
>>
> 
> But in "most cases" there is so little memory allocated
> that the equivalent free() calls will take practically
> zero time anyway. In the cases that a ton of memory is
> used, then the OS has its work set out for it whether or
> not the code is explicitly calling free().
> 

you have no idea how modern OSes work apparently


0
Reply jacob31 (869) 2/16/2010 6:50:56 PM

Seebs <usenet-nospam@seebs.net> wrote:

> On 2010-02-16, Ertugrul S=C3=B6ylemez <es@ertes.de> wrote:
> > So still there is no excuse for not freeing memory.
>
> Again, there are a couple.  However, they're usually system-specific.
> I can point you at an obvious case, although it's not portable:  If
> you wish to execute another program in a UNIX-like environment, you
> almost certainly need to allocate the space for its argument
> list... And then your program exits to exec the other program.  You
> must not free the memory before calling exec(), and after exec(), you
> don't exist.

Of course, but as you say that's system-specific and you're left with no
choice anyway.  But if you have a choice, you should choose correctness
over small performance gains.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/16/2010 7:03:15 PM

On 2010-02-16, jacob navia <jacob@spamsink.net> wrote:
> Andrew Poelstra a �crit :
>> And if this was an embedded system, eventually
>> the watchdog would kick and the programmer would (hopefully)
>> realize that his code was buggy and needed fixing.
>>
>
> the code is not buggy.
>

It takes memory from the OS and never gives it back.
In what world would this oversight not be a bug?

>
>>> I have never seen an OS that did not do that.
>> 
>> Again, in embedded systems many OS's choose not to support
>> bad programming. There are no users downloading garbage
>> from the Internet and blithely expecting it to run despite
>> barely being compilable.
>> 
>
> OK. In your pet os (with lowercase) a program that has
> a memory leak will bring the whole system down.
>

Eventually it will, if you run it enough times that it
uses all of the memory in the system. And then it will
reset and likely be called again. So "problem solved",
aside from the unnecessary reboot and consequential
power usage.

> GREAT SYSTEM!
>

Well, it works, as above.

CPU cycles are not unlimited. Spending them trying to
save inattentive programmers who don't keep track of
their resources is not always a good investment.

0
Reply apoelstra (387) 2/16/2010 7:06:58 PM

On 2010-02-16, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> On 2010-02-16, jacob navia <jacob@spamsink.net> wrote:
>> the code is not buggy.

> It takes memory from the OS and never gives it back.
> In what world would this oversight not be a bug?

One in which we expect the operating system to manage resources.

Which is actually pretty much the point of calling something an
"operating system".

If the OS doesn't know which programs have which resources, it's already
failed.

> CPU cycles are not unlimited. Spending them trying to
> save inattentive programmers who don't keep track of
> their resources is not always a good investment.

It turns out, though, that marking the few megabytes a process used to
have as "no longer in use" is much, much, cheaper than having the process
try to walk through a ton of complicated data structures.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 7:28:38 PM

On 2010-02-16, Ertugrul S�ylemez <es@ertes.de> wrote:
> Of course, but as you say that's system-specific and you're left with no
> choice anyway.  But if you have a choice, you should choose correctness
> over small performance gains.

In general, I agree.  In practice, though, I don't see anything intrinsically
wrong with a system guaranteeing that certain classes of resources are
automatically deallocated on exit, and relying on that behavior.

How many people have you seen close stdout, stderr, and stdin at the end
of a program?  Why don't they do that?  You'd normally close any file that
was previously open, right?

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 7:30:02 PM

In article <slrnhnllpj.j8j.usenet-nospam@guild.seebs.net>, Seebs <usenet-nospam@seebs.net> writes:

> So the fact remains:  In general, on all the major platforms in use, there is
> no possible case where calling free() a lot right before termination can make
> things any better, and there are many obvious cases where they can make things
> worse by orders of magnitude.

It has a development-related side, too. Freeing everything correctly in
the end
- increases understanding of inter-object ownerships,
- helps debugging with valgrind or one's custom allocator,
- makes it easier to embed the program into another program (or
  library).

Perhaps such a final cleanup should depend on a compile time (or
runtime) toggle.

It is not easy to spot a leak if everything is leaked in case of a
successful exit. If suddenly the program must do the same thing in a
loop, leaking becomes an issue.

Cheers,
lacos
0
Reply lacos (176) 2/16/2010 7:38:42 PM

Seebs <usenet-nospam@seebs.net> wrote:

> On 2010-02-16, Ertugrul S=C3=B6ylemez <es@ertes.de> wrote:
> > Of course, but as you say that's system-specific and you're left
> > with no choice anyway.  But if you have a choice, you should choose
> > correctness over small performance gains.
>
> In general, I agree.  In practice, though, I don't see anything
> intrinsically wrong with a system guaranteeing that certain classes of
> resources are automatically deallocated on exit, and relying on that
> behavior.

It is good that the operating system does that, but it's wrong to rely
on that feature.


> How many people have you seen close stdout, stderr, and stdin at the
> end of a program?  Why don't they do that?  You'd normally close any
> file that was previously open, right?

You're not supposed to close the std-handles, because you have not
opened them.  You are responsible for closing/freeing resources you have
opened/allocated yourself.  For many resources there is even a stack of
allocations, which you should follow.  The pattern looks like this:

  <file1>
    <file2>
      <someCode />
      <file3>
        <someCode />
      </file3>
      <someCode />
    </file2>
  </file1>

As your main function is entered, there are already three of those file
tags open, one for each of stdin, stdout and stderr and possibly some
others.  Closing one of the handles is the same as putting a closing tag
too early.  Because of system peculiarities you may be forced to do
that, but it's better to avoid for the sake of consistency.  Closing a
resource prematurely is just as wrong as closing it too late (or not
closing it at all).

That's also the reason I suggest freeing all of the allocated memory
before exiting.  If you don't, there is a closing tag missing in your
program pattern.  When you restructure your program, you might
accidentally forget that missing closing tag and introduce memory leaks.
You know how difficult it can be to find memory leaks, if you ever
notice them at all.

The CPS-based resource management function I proposed solves this
problem to some extent, because every resource has a clear scope, and
without abusing global/static variables, it can't even escape that
scope.  In other words, the closing tag is enforced in the pattern.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/16/2010 8:28:06 PM

Seebs <usenet-nospam@seebs.net> wrote:

> On 2010-02-16, Ertugrul S=C3=B6ylemez <es@ertes.de> wrote:
> > Of course, but as you say that's system-specific and you're left
> > with no choice anyway.  But if you have a choice, you should choose
> > correctness over small performance gains.
>
> In general, I agree.  In practice, though, I don't see anything
> intrinsically wrong with a system guaranteeing that certain classes of
> resources are automatically deallocated on exit, and relying on that
> behavior.

It is good that the operating system does that, but it's wrong to rely
on that feature.


> How many people have you seen close stdout, stderr, and stdin at the
> end of a program?  Why don't they do that?  You'd normally close any
> file that was previously open, right?

You're not supposed to close the std-handles, because you have not
opened them.  You are responsible for closing/freeing resources you have
opened/allocated yourself.  For many resources there is even a stack of
allocations, which you should follow.  The pattern looks like this:

  <file1>
    <file2>
      <someCode />
      <file3>
        <someCode />
      </file3>
      <someCode />
    </file2>
  </file1>

As your main function is entered, there are already three of those file
tags open, one for each of stdin, stdout and stderr and possibly some
others.  Closing one of the handles is the same as putting a closing tag
too early.  Because of system peculiarities you may be forced to do
that, but it's better to avoid for the sake of consistency.  Closing a
resource prematurely is just as wrong as closing it too late (or not
closing it at all).

That's also the reason I suggest freeing all of the allocated memory
before exiting.  If you don't, there is a closing tag missing in your
program pattern.  When you restructure your program, you might
accidentally forget that missing closing tag and introduce memory leaks.
You know how difficult it can be to find memory leaks, if you ever
notice them at all.

The CPS-based resource management function I proposed solves this
problem to some extent, because every resource has a clear scope, and
without abusing global/static variables, it can't even escape that
scope.  In other words, the closing tag is enforced in the pattern.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/16/2010 8:28:26 PM

In article <slrnhnlshq.n2l.usenet-nospam@guild.seebs.net>, Seebs <usenet-nospam@seebs.net> writes:

> How many people have you seen close stdout, stderr, and stdin at the end
> of a program?  Why don't they do that?

Because they didn't open them in the first place. *Flushing* stdout is
another thing, of course. Stderr is generally not flushed because it is
never fully buffered per default, and sane programs write line-oriented
diagnostics anyway. (Progress indicators more advanced than
line-oriented diagnostics but still not quite on the curses level should
go through /dev/tty.)

I did close stdin / stdout in some of my utilities. I'm not sure if this
is allowed, even looking at fclose() / freopen() -- at least on OpenVMS
this triggered elaborate crashes, and generally, I guess even external
utilities accessing processes through /proc expect fd's 0, 1 and 2 to
have their original meanings. Daemons don't close their standard I/O
streams or the file descriptors underneath them, they redirect them from
(to) /dev/null.


> You'd normally close any file that
> was previously open, right?

If I was the one to open it, then yes.

Cheers,
lacos
0
Reply lacos (176) 2/16/2010 8:34:10 PM

Seebs <usenet-nospam@seebs.net> wrote:

> On 2010-02-16, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> > On 2010-02-16, jacob navia <jacob@spamsink.net> wrote:
> >> the code is not buggy.
>
> > It takes memory from the OS and never gives it back.  In what world
> > would this oversight not be a bug?
>
> One in which we expect the operating system to manage resources.
>
> Which is actually pretty much the point of calling something an
> "operating system".

It is a bug, but some people tolerate it, some don't.  What the
operating system does here is not called resource management, but fault
tolerance.  It should be designed not to fail on programming errors.

It's wrong in a similar way to keep helper threads running, but the
operating system is not fault tolerant in this case, so it would in fact
lead to a system crash sooner or later.


> If the OS doesn't know which programs have which resources, it's
> already failed.

If a program launches several worker threads and then daemonizes, the
operating system generally loses track of the relations.


> > CPU cycles are not unlimited. Spending them trying to save
> > inattentive programmers who don't keep track of their resources is
> > not always a good investment.
>
> It turns out, though, that marking the few megabytes a process used to
> have as "no longer in use" is much, much, cheaper than having the
> process try to walk through a ton of complicated data structures.

In times, where you measure processor cycles in GHz and available memory
in GiB and where the complexity of applications gets huge, it's very
dangerous to go with program exiting (!) performance.  In general you
will prefer correctness and predictability over a slightly faster
process exit.

Remember we're not talking about in-program performance here.  We are
talking about program shutdown.  Also even walking a data structure with
millions of branches takes less than a second on today's machines.


Greets
Ertugrul


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/16/2010 8:42:07 PM

On 2/16/2010 3:42 PM, Ertugrul S�ylemez wrote:
> It is a bug, but some people tolerate it, some don't.  What the
> operating system does here is not called resource management, but fault
> tolerance.  It should be designed not to fail on programming errors.

What a bizarre notion. What happens to the resources of a
program when the program exits is defined by the operating
system. Relying on OS-defined behavior in your program is
not an error. Performing time-wasting activity on abstract
grounds of illusory correctness, on the other hand, is an
error.
0
Reply hyrosen (1792) 2/16/2010 8:56:42 PM

Hyman Rosen <hyrosen@mail.com> wrote:

> On 2/16/2010 3:42 PM, Ertugrul S=C3=B6ylemez wrote:
> > It is a bug, but some people tolerate it, some don't.  What the
> > operating system does here is not called resource management, but
> > fault tolerance.  It should be designed not to fail on programming
> > errors.
>
> What a bizarre notion. What happens to the resources of a program when
> the program exits is defined by the operating system. Relying on
> OS-defined behavior in your program is not an error. Performing
> time-wasting activity on abstract grounds of illusory correctness, on
> the other hand, is an error.

You're showing that you are an irresponsible programmer.  C and Cobol
are about the only languages in wide-spread use, which even allow that
kind of carelessness.  Modern languages are even designed to prevent you
from being stupid.  But obviously you want to be stupid.

Relying on operating system fault tolerance is wrong and most good
programmers will agree, at the very least because they want their
programs to be portable, well structured and modular.  Even basic
constructs of modern programming languages like OOP disagree with you.

And as said, your irresponsible attitude will bite you as soon as you
need to rewrite parts of your program.  Your coding style (relying on
environmental properties) is highly nonmodular.  Modularity is the key
to maintainability, and if you disagree here, you're just ridiculous and
nobody will take you seriously anyway.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/16/2010 10:00:30 PM

On Feb 16, 3:56=A0pm, Hyman Rosen <hyro...@mail.com> wrote:
> On 2/16/2010 3:42 PM, Ertugrul S=F6ylemez wrote:
>
> > It is a bug, but some people tolerate it, some don't. =A0What the
> > operating system does here is not called resource management, but fault
> > tolerance. =A0It should be designed not to fail on programming errors.
>
> What a bizarre notion. What happens to the resources of a
> program when the program exits is defined by the operating
> system. Relying on OS-defined behavior in your program is
> not an error. Performing time-wasting activity on abstract
> grounds of illusory correctness, on the other hand, is an
> error.

Do you differentiate between detecting memory that is considered a
leak versus memory that you allow the OS to cleanup?  I would think it
would be a benefit to know if the application *can* shutdown cleanly
so that memory leaks could be determined.  Whether you consider that
time-wasting is up to you.  Does that attitude also extend to library
development?

What's your opinion on other I/O sources?  Do you bother to close
files, sockets, database connections, or do you also depend on the
underlying architecture to "do the right thing"?

I'm biased this way since I have not encountered a situation where the
shutdown time/complexity is an issue, but maybe you have.

Best regards,
John D.
0
Reply jadill33 (201) 2/16/2010 10:09:26 PM

On 2/16/2010 5:09 PM, ImpalerCore wrote:
> Do you differentiate between detecting memory that is considered a
> leak versus memory that you allow the OS to cleanup?

That's what I said originally - the program should act
the way a garbage collector does. If it's leaking memory
by losing track of it, then the program is likely broken.
If it's simply building up very large data structures,
but they're all reachable, then there's no need to clean
up that memory before exiting.

 > Does that attitude also extend to library development?

Which attitude? If a library offers ways to build up
structures, it should offer a way to tear them down.
Whether those tear downs should be invoked by the program
before exiting will depend on what they do.

> What's your opinion on other I/O sources?  Do you bother to close
> files, sockets, database connections, or do you also depend on the
> underlying architecture to "do the right thing"?

That depends. Files are usually encapsulated by data
structures that cache writes before committing to the
operating system, so a finalization step is needed to
make sure that the caches are flushed. I think, but I
am not sure, that it is harmless to let a database
connection die with the program, if the program is
accessing the database in small self-contained actions
(e.g., not holding a transaction open for the duration
of the session).

But other resources are seldom held in the numbers of
which allocated objects are held. It does not take long
to close a handful of files or connections. It can take
very long to free millions of pieces of memory. And doing
so accomplishes nothing.

> I'm biased this way since I have not encountered a situation where the
> shutdown time/complexity is an issue, but maybe you have.

I have.
0
Reply hyrosen (1792) 2/16/2010 10:24:25 PM

On Feb 16, 5:24=A0pm, Hyman Rosen <hyro...@mail.com> wrote:
> On 2/16/2010 5:09 PM, ImpalerCore wrote:
>
> > Do you differentiate between detecting memory that is considered a
> > leak versus memory that you allow the OS to cleanup?
>
> That's what I said originally - the program should act
> the way a garbage collector does. If it's leaking memory
> by losing track of it, then the program is likely broken.
> If it's simply building up very large data structures,
> but they're all reachable, then there's no need to clean
> up that memory before exiting.
>
> =A0> Does that attitude also extend to library development?
>
> Which attitude? If a library offers ways to build up
> structures, it should offer a way to tear them down.
> Whether those tear downs should be invoked by the program
> before exiting will depend on what they do.
>
> > What's your opinion on other I/O sources? =A0Do you bother to close
> > files, sockets, database connections, or do you also depend on the
> > underlying architecture to "do the right thing"?
>
> That depends. Files are usually encapsulated by data
> structures that cache writes before committing to the
> operating system, so a finalization step is needed to
> make sure that the caches are flushed. I think, but I
> am not sure, that it is harmless to let a database
> connection die with the program, if the program is
> accessing the database in small self-contained actions
> (e.g., not holding a transaction open for the duration
> of the session).
>
> But other resources are seldom held in the numbers of
> which allocated objects are held. It does not take long
> to close a handful of files or connections. It can take
> very long to free millions of pieces of memory. And doing
> so accomplishes nothing.
>
> > I'm biased this way since I have not encountered a situation where the
> > shutdown time/complexity is an issue, but maybe you have.
>
> I have.

Care to elaborate?
0
Reply jadill33 (201) 2/16/2010 10:45:07 PM

On 2010-02-16, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> Again, in embedded systems many OS's choose not to support

I doubt you could name one, and if you could, that you could
get someone to pay you a dime to develop something for it.

> bad programming. There are no users downloading garbage

A program implements some sort of specification. In commercial development,
the specification is usually a concrete document.

Your specification is that of a hobbyist; you have in mind the idea of a
a maximally portable program which tidies up after itself.

But a program which doesn't meet your academic ideal of what
constitutes a good program is not a bad program. 

A ``bad'' program is one which, firstly, doesn't meet its specification,
whatever that is, and secondly, one which implements a faulty specification.

A specification which says that the program need not clean up after itself is
rationally justifiable.  The functionality of process cleanup is already
implemented in the intended target platforms: it is found in one place which
has been well debugged. For you to contravene the specification and start
adding superfluous code to the program would be bad programming.

Code carries a risk. Unnecessary code carries unnecessary risk.
Unnecessary risk is never acceptable.

Many platforms which clean up after a program can do so even if the program
has misused dynamic memory (e.g. overran or underran a buffer). They can do
it even if the program has terminated abnormally and abruptly, possibly even
if that happened while the program was executing the memory allocator itself.

It is a bad strategy for a portable program to be written such that it treats
reliable target platforms as if they were unreliable. So the ``one size fits
all'' idea of a maximally portable program without any conditional
compilation is actually bad design. One design for every situation is
poor engineering. 

>> No, in most cases it will use a single free() call
>> since all memory allocated for a process will be in
>> a single heap.
>>
>
> But in "most cases" there is so little memory allocated
> that the equivalent free() calls will take practically
> zero time anyway. In the cases that a ton of memory is
> used, then the OS has its work set out for it whether or
> not the code is explicitly calling free().

You persist in being techincally wrong here, demostrating a gaping lack of
knowledge about mainstream platforms and their middleware.

On most platforms, calling free on every outstanding object
prior to termination will not subtract from any of the execution
time that is subsequently required to clean up that process.
0
Reply kkylheku (2499) 2/16/2010 11:05:26 PM

On 2010-02-16, Hyman Rosen <hyrosen@mail.com> wrote:
> On 2/16/2010 3:42 PM, Ertugrul Söylemez wrote:
>> It is a bug, but some people tolerate it, some don't.  What the
>> operating system does here is not called resource management, but fault
>> tolerance.  It should be designed not to fail on programming errors.
>
> What a bizarre notion. What happens to the resources of a
> program when the program exits is defined by the operating
> system. Relying on OS-defined behavior in your program is
> not an error. Performing time-wasting activity on abstract
> grounds of illusory correctness, on the other hand, is an
> error.

Not only is it compute-time wasting, it is developer-time wasting
to develop it.

Furthermore, the code carries a risk. Since the code is unnecessary,
the risk is unnecessary.

It's difficult to justify unnecessary risk.
0
Reply kkylheku (2499) 2/16/2010 11:10:33 PM

On 2010-02-16, Ertugrul Söylemez <es@ertes.de> wrote:
> Hyman Rosen <hyrosen@mail.com> wrote:
>
>> On 2/16/2010 3:42 PM, Ertugrul Söylemez wrote:
>> > It is a bug, but some people tolerate it, some don't.  What the
>> > operating system does here is not called resource management, but
>> > fault tolerance.  It should be designed not to fail on programming
>> > errors.
>>
>> What a bizarre notion. What happens to the resources of a program when
>> the program exits is defined by the operating system. Relying on
>> OS-defined behavior in your program is not an error. Performing
>> time-wasting activity on abstract grounds of illusory correctness, on
>> the other hand, is an error.
>
> You're showing that you are an irresponsible programmer.  C and Cobol
> are about the only languages in wide-spread use, which even allow that
> kind of carelessness.  Modern languages are even designed to prevent you
> from being stupid.  But obviously you want to be stupid.

What modern languages would those be? I suspect you could not name one
such that you are not wrong.

In any language that can be called modern, allocate objects without
concern for how they will be freed.

> Relying on operating system fault tolerance is wrong and most good

It's not fault tolerance but resource management. You are pitifully
wrong in your other posting.

Relying on this is no more wrong than relying on a TCP/IP stack,
graphics display, or DMA transfers.

> It's no
> programmers will agree, at the very least because they want their
> programs to be portable

Programmers who get paid for a living want their programs to be portable in a
way that is /economically/ relevant, balanced with other requirements.  

Maximal portability, the kind where we pretend we write a single body of
source code without conditionl compilation while pretending we programming
for an incapable, broken platform, is only an obsession of a few dull minds.

That should come as no surprise: it requires a lower level reasoning than
doing a crossword puzzle from the newspaper.

> Modularity is the key
> to maintainability, and if you disagree here, you're just ridiculous and
> nobody will take you seriously anyway.

Without automatic storage managament, there is no real modularity.  Modules
are coupled together by the distributed responsibility of memory management.
It creeps into all the interfaces: who allocates what and who will free it.

It's laughable to advocate explicit storage deallocation and modularity in
the same breath.
0
Reply kkylheku (2499) 2/16/2010 11:17:35 PM

On 2010-02-16, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> I am going to disagree with you on this point: on my system, if a program
> cleans up its own memory, I see a delay between clicking the X (or Ctrl+C,
> or whatever) and the program actually dying. During this time it does its
> cleanup, plays with the hard drive and whatever. Meanwhile, I am free to
> do other things.
>
> However, if the program just dies, I see a quick and painless exit. And
> then the kernel takes over to do cleanup, which has a higher priority than
> the dead program. And while it's cleaning up, the rest of my system is
> sluggish, even if only for a second.

ROFL.

I'd like a word with the prof who taught you Operating Systems 301.
0
Reply kkylheku (2499) 2/16/2010 11:20:55 PM

Hyman Rosen a �crit :
> On 2/16/2010 5:09 PM, ImpalerCore wrote:
>> Do you differentiate between detecting memory that is considered a
>> leak versus memory that you allow the OS to cleanup?
> 
> That's what I said originally - the program should act
> the way a garbage collector does. If it's leaking memory
> by losing track of it, then the program is likely broken.
> If it's simply building up very large data structures,
> but they're all reachable, then there's no need to clean
> up that memory before exiting.
> 
>  > Does that attitude also extend to library development?
> 
> Which attitude? If a library offers ways to build up
> structures, it should offer a way to tear them down.
> Whether those tear downs should be invoked by the program
> before exiting will depend on what they do.
> 
>> What's your opinion on other I/O sources?  Do you bother to close
>> files, sockets, database connections, or do you also depend on the
>> underlying architecture to "do the right thing"?
> 
> That depends. Files are usually encapsulated by data
> structures that cache writes before committing to the
> operating system, so a finalization step is needed to
> make sure that the caches are flushed. I think, but I
> am not sure, that it is harmless to let a database
> connection die with the program, if the program is
> accessing the database in small self-contained actions
> (e.g., not holding a transaction open for the duration
> of the session).
> 
> But other resources are seldom held in the numbers of
> which allocated objects are held. It does not take long
> to close a handful of files or connections. It can take
> very long to free millions of pieces of memory. And doing
> so accomplishes nothing.
> 
>> I'm biased this way since I have not encountered a situation where the
>> shutdown time/complexity is an issue, but maybe you have.
> 
> I have.

Me too.

The lcc-win compiler never calls free(). Since windows will
free the memory used by the compiler, it is pointless to spend
time freeing everything. The same holds for lcc-win under linux
and Mac OS X.

In a compiler, the complicated structures needed by the building
of the compilation context are needed to the very end of the
program.

Symbol tables must be present so that the assembler knows which
globals must be emitted, after all code generation is done.

Each scope is allocated and then released, of course, to avoid
using up too much memory, but this is not done with free().
Each function allocates all its transient data structures
(entries for local variables, local declarations, etc) in
a single heap that is released with a single pointer assignment,
like a stack.

In fact, each statement allocates data structures that are released
in the same fashion (stack-like). But all the data allocated
with malloc that is global is retained, and never released,
assuming the OS will do that. This has been working reliably
since at least 2002-2003, when I eliminated all calls to
free() and eliminated all code that was doing the cleanup before
exiting.

Note that the order of freeing is very strict. You can never free an
object until all the objects that it contains are freed. Freeing
all the interconnected data structures can be dangerous since it
could provoke a trap. Much simpler is just to eliminate that
code.

The same is true for the linker. There, the situation is even more
drastic since you can't free anything until the very end. Why
should the linker do that? Just exiting to the OS will free
everything anyway.

Both the compiler and the linker are very fast. ANd that is a
feature users appreciate, more than some hypothetical
"correctness".

0
Reply jacob31 (869) 2/16/2010 11:21:28 PM

On 2010-02-16, Ertugrul S�ylemez <es@ertes.de> wrote:
> It is good that the operating system does that, but it's wrong to rely
> on that feature.

I don't agree that it is necessarily wrong to rely on OS features.

>> How many people have you seen close stdout, stderr, and stdin at the
>> end of a program?  Why don't they do that?  You'd normally close any
>> file that was previously open, right?

> You're not supposed to close the std-handles, because you have not
> opened them.

What if I have?  ("freopen()")

Am I obliged to try to fclose() stderr if I have opened it with freopen()?

> As your main function is entered, there are already three of those file
> tags open, one for each of stdin, stdout and stderr and possibly some
> others.  Closing one of the handles is the same as putting a closing tag
> too early.  Because of system peculiarities you may be forced to do
> that, but it's better to avoid for the sake of consistency.  Closing a
> resource prematurely is just as wrong as closing it too late (or not
> closing it at all).

Okay, that's a good argument.  In light of that, I'd guess that your answer
to the freopen() question would be, no, you don't have to close that, because
the environment is still expected to close stderr if it needs to, etc.

> That's also the reason I suggest freeing all of the allocated memory
> before exiting.  If you don't, there is a closing tag missing in your
> program pattern.  When you restructure your program, you might
> accidentally forget that missing closing tag and introduce memory leaks.
> You know how difficult it can be to find memory leaks, if you ever
> notice them at all.

I actually have a memory debugger I wrote to find them.  As you might expect,
it couldn't solve the actual problem.

Because, technically, it wasn't a leak -- when I went through freeing
everything at the end of program execution, all the allocated space got
freed.  However.  During execution, it was possible for a particular object
to end up with a linked list of unbounded size of allocated things that it
maintained as internal state, which were neither used nor exposed to any
other interface, making it very hard to find them -- and since it did free
them correctly on exit, there was no memory leak.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 11:35:28 PM

On 2010-02-16, Ertugrul S�ylemez <es@ertes.de> wrote:
> It is a bug, but some people tolerate it, some don't.  What the
> operating system does here is not called resource management, but fault
> tolerance.  It should be designed not to fail on programming errors.

But it's not necessarily a programming error to let the operating system
deallocate resources.  It'd be a programming error if that were contrary to
the documented behavior of the OS.  Otherwise, it may well be intentional
and well-considered.

> If a program launches several worker threads and then daemonizes, the
> operating system generally loses track of the relations.

On unix-like stuff, as long as they are actually *threads*, it usually
doesn't.

>> It turns out, though, that marking the few megabytes a process used to
>> have as "no longer in use" is much, much, cheaper than having the
>> process try to walk through a ton of complicated data structures.

> In times, where you measure processor cycles in GHz and available memory
> in GiB and where the complexity of applications gets huge, it's very
> dangerous to go with program exiting (!) performance.  In general you
> will prefer correctness and predictability over a slightly faster
> process exit.

I'm not convinced.  There are a lot of programs which are, by design, run
EXTREMELY often.

> Remember we're not talking about in-program performance here.  We are
> talking about program shutdown.  Also even walking a data structure with
> millions of branches takes less than a second on today's machines.

I do a lot of work on a build system.  In the course of a single run of the
build system, there are programs that get run upwards of a hundred thousand
times.  (Say, the shell.)  In that case, I think it makes a great deal of
sense to think very carefully about performance of startup and exit.

Which is why it's useful to know what the operating system's designed
semantics are.  One could easily imagine an operating system where a
particular device could only accept full-block writes of, say, 512 bytes.
However, we don't then say that it is a "programming error" to ever write
to any device except in 512-byte blocks...

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 11:39:07 PM

On 2010-02-16, Ertugrul S�ylemez <es@ertes.de> wrote:
> You're showing that you are an irresponsible programmer.  C and Cobol
> are about the only languages in wide-spread use, which even allow that
> kind of carelessness.  Modern languages are even designed to prevent you
> from being stupid.  But obviously you want to be stupid.
[...]
> and if you disagree here, you're just ridiculous and
> nobody will take you seriously anyway.

I'm curious, do you come from a culture in which there is any conceivable
way that insulting people like this leads to positive outcomes?

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 11:45:58 PM

On 2010-02-16, ImpalerCore <jadill33@gmail.com> wrote:
> Do you differentiate between detecting memory that is considered a
> leak versus memory that you allow the OS to cleanup?

I certainly do.

> I would think it
> would be a benefit to know if the application *can* shutdown cleanly
> so that memory leaks could be determined.  Whether you consider that
> time-wasting is up to you.  Does that attitude also extend to library
> development?

It depends a lot on circumstances.  Generally, at the least, I'd expect to
know which pieces of storage I'm allocating that I expect to still be there
at the end of execution.

> What's your opinion on other I/O sources?  Do you bother to close
> files, sockets, database connections, or do you also depend on the
> underlying architecture to "do the right thing"?

That also depends quite a bit on circumstances.  I usually close files, but
there have been exceptions.

As an example, I have a hunk of code I maintain right now, in which a few
files are opened, and a few resources allocated, which are not released on
exit -- because this hunk of code is intercepting the actions of other
programs, and does not necessarily know about their exits.  More importantly,
it is fairly trivial to prove that even if I tried to intercept their exits,
I could not do so safely.  Either I would deallocate my resources at a time
when the other program could then perform actions which still required them,
or I would have to leave them allocated until a point at which nothing was
going to transfer control back to me.  Can't win.

> I'm biased this way since I have not encountered a situation where the
> shutdown time/complexity is an issue, but maybe you have.

I have.  I once had a program which took over five seconds to exit on what
was, at the time, a very fast machine.  In that case, I swapped a key data
structure from an array of pointers to an array of objects, and it got faster
by, well, about a factor of eighty, which was good enough.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/16/2010 11:49:35 PM

Seebs wrote:
> On 2010-02-16, Ertugrul S�ylemez <es@ertes.de> wrote:
>> Of course, but as you say that's system-specific and you're left with no
>> choice anyway.  But if you have a choice, you should choose correctness
>> over small performance gains.
> 
> In general, I agree.  In practice, though, I don't see anything intrinsically
> wrong with a system guaranteeing that certain classes of resources are
> automatically deallocated on exit, and relying on that behavior.

In practice, I do see something wrong with relying on that behaviour, 
and my opinion is based on experience of a (fairly large - several 
hundred thousand lines) program that did rely on that behaviour. I 
didn't write it, but I did have to help fix it.

In bare outline, it worked like this:

main()
{
   lots_of_functions_that_do_not_bother_to_clean_up();
}

And then, one day, it got maintained, as programs do:

func()
{
   lots_of_functions_that_do_not_bother_to_clean_up();
}

main()
{
   for(big_old_loop)
   {
     func();
   }
}

Suddenly we had a huge maintenance problem on our hands because the 
original crew were too lazy to manage memory properly. This cost a 
significant amount of time (and therefore money) to fix, because the 
knowledge of the right points at which to free up the many and varied 
allocations had been discarded, and now had to be reacquired.

> How many people have you seen close stdout, stderr, and stdin at the end
> of a program?  Why don't they do that?  You'd normally close any file that
> was previously open, right?

No, you'd normally close any file that you opened; stdin, stdout, and 
stderr are special cases. But I do close files that I've opened, even 
though I know that they are guaranteed to be closed when the program 
quits. Why? Because I recognise the possibility that main() may become 
func(), that's why.

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 2/17/2010 12:29:53 AM

["Followup-To:" header set to comp.lang.c.]
On 2010-02-17, Richard Heathfield <rjh@see.sig.invalid> wrote:
> Seebs wrote:
>> On 2010-02-16, Ertugrul Söylemez <es@ertes.de> wrote:
>>> Of course, but as you say that's system-specific and you're left with no
>>> choice anyway.  But if you have a choice, you should choose correctness
>>> over small performance gains.
>> 
>> In general, I agree.  In practice, though, I don't see anything intrinsically
>> wrong with a system guaranteeing that certain classes of resources are
>> automatically deallocated on exit, and relying on that behavior.
>
> In practice, I do see something wrong with relying on that behaviour, 
> and my opinion is based on experience of a (fairly large - several 
> hundred thousand lines) program that did rely on that behaviour. I 
> didn't write it, but I did have to help fix it.
>
> In bare outline, it worked like this:
>
> main()
> {
>    lots_of_functions_that_do_not_bother_to_clean_up();
> }
>
> And then, one day, it got maintained, as programs do:
>
> func()
> {
>    lots_of_functions_that_do_not_bother_to_clean_up();
> }
>
> main()
> {
>    for(big_old_loop)
>    {
>      func();
>    }
> }
>
> Suddenly we had a huge maintenance problem on our hands because the 
> original crew were too lazy to manage memory properly. This cost a 
> significant amount of time (and therefore money) to fix, because the 
> knowledge of the right points at which to free up the many and varied 
> allocations had been discarded, and now had to be reacquired.

You wasted your time and money only because you didn't think of redirecting
the functions to use an alternate malloc-like API which keeps track of the
allocations, such that they can be freed with an additional call when func()
exits:

 main()
 {
   for(big_old_loop)
   {
      heap *h = heap_create();
      func(h);
      heap_dispose(h);
   }
 }

func stores h in a global variable somewhere:

  extern heap *my_heap;

  void func(heap *h)
  {
     my_heap = h;
  }
  
calls like

  obj *p = (obj *) malloc(sizeof *p);

are replaced with:

  obj *p = (obj *) heap_alloc(my_heap, sizeof *p);

or through a wrapper which looks like malloc.

This is not a ``huge maintenance problem''.

The original programmer did the right thing by not wasting time on this
problem.  The new use case was not a functional requirement for that program.
0
Reply kkylheku (2499) 2/17/2010 12:46:34 AM

Kaz Kylheku wrote:
> ["Followup-To:" header set to comp.lang.c.]
> On 2010-02-17, Richard Heathfield <rjh@see.sig.invalid> wrote:
<snip>

>> Suddenly we had a huge maintenance problem on our hands because the 
>> original crew were too lazy to manage memory properly. This cost a 
>> significant amount of time (and therefore money) to fix, because the 
>> knowledge of the right points at which to free up the many and varied 
>> allocations had been discarded, and now had to be reacquired.
> 
> You wasted your time and money only because you didn't think of redirecting
> the functions to use an alternate malloc-like API which keeps track of the
> allocations, such that they can be freed with an additional call when func()
> exits:

It's true that we didn't think of such a scheme. Even if we had, though, 
either we'd have had to visit every malloc and free to replace them with 
the meta-memory-management function calls, or we'd have had to redefine 
malloc(). The latter would have been unacceptable, I think. The former 
may have saved us a little time, though, if we had thought of it.

But the time saving would have been optimum if the original programmer 
had done his job correctly.

<snip>

> The original programmer did the right thing by not wasting time on this
> problem.  The new use case was not a functional requirement for that program.

I am reminded of the student who, when asked to write a program to add 
two numbers together and print the result, asked the lecturer "which two 
numbers should I add?"

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 2/17/2010 1:13:25 AM

On 2010-02-17, Richard Heathfield <rjh@see.sig.invalid> wrote:
> main()
> {
>    lots_of_functions_that_do_not_bother_to_clean_up();
> }
>
> And then, one day, it got maintained, as programs do:
>
> func()
> {
>    lots_of_functions_that_do_not_bother_to_clean_up();
> }

Ahh, I see.

I don't do it that way.  The only time I abandon cleanup is when there
is no reason to allocate something again once it's allocated -- if I
thought a new pass might allocate the same resources, then I would indeed
free them up.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/17/2010 1:18:05 AM

Richard Heathfield wrote:
> Kaz Kylheku wrote:
>> ["Followup-To:" header set to comp.lang.c.]
>> On 2010-02-17, Richard Heathfield <rjh@see.sig.invalid> wrote:
> <snip>
> 
>>> Suddenly we had a huge maintenance problem on our hands because the 
>>> original crew were too lazy to manage memory properly. This cost a 
>>> significant amount of time (and therefore money) to fix, because the 
>>> knowledge of the right points at which to free up the many and varied 
>>> allocations had been discarded, and now had to be reacquired.
>>
>> You wasted your time and money only because you didn't think of 
>> redirecting
>> the functions to use an alternate malloc-like API which keeps track of 
>> the
>> allocations, such that they can be freed with an additional call when 
>> func()
>> exits:
> 
> It's true that we didn't think of such a scheme. Even if we had, though, 
> either we'd have had to visit every malloc and free to replace them with 
> the meta-memory-management function calls, or we'd have had to redefine 
> malloc(). The latter would have been unacceptable, I think. The former 
> may have saved us a little time, though, if we had thought of it.
> 
> But the time saving would have been optimum if the original programmer 
> had done his job correctly.
> 
> <snip>
> 
>> The original programmer did the right thing by not wasting time on this
>> problem.  The new use case was not a functional requirement for that 
>> program.
> 
> I am reminded of the student who, when asked to write a program to add 
> two numbers together and print the result, asked the lecturer "which two 
> numbers should I add?"
> 
bmaxa@maxa:~$ strace -f -e mmap java -version
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7f20a9c94000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7f20a9c92000
mmap(NULL, 127378, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f20a9c72000
mmap(NULL, 2208640, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0x7f20a985b000
mmap(0x7f20a9a71000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16000) = 0x7f20a9a71000
mmap(0x7f20a9a73000, 13184, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f20a9a73000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7f20a9c71000
mmap(NULL, 1089200, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0x7f20a9b67000
mmap(0x7f20a9c6f000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x8000) = 0x7f20a9c6f000
mmap(NULL, 2109696, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0x7f20a9657000
mmap(0x7f20a9859000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f20a9859000
mmap(NULL, 3598344, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0x7f20a92e8000
mmap(0x7f20a964d000, 20480, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x165000) = 0x7f20a964d000
mmap(0x7f20a9652000, 18440, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f20a9652000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7f20a9b66000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7f20a9b65000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7f20a9c91000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7ffd0b87f000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7ffd0b87d000
mmap(NULL, 127378, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffd0b85d000
mmap(NULL, 2208640, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0x7ffd0b446000
mmap(0x7ffd0b65c000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16000) = 0x7ffd0b65c000
mmap(0x7ffd0b65e000, 13184, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b65e000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7ffd0b85c000
mmap(NULL, 1089200, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0x7ffd0b752000
mmap(0x7ffd0b85a000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x8000) = 0x7ffd0b85a000
mmap(NULL, 2109696, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0x7ffd0b242000
mmap(0x7ffd0b444000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7ffd0b444000
mmap(NULL, 3598344, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0x7ffd0aed3000
mmap(0x7ffd0b238000, 20480, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x165000) = 0x7ffd0b238000
mmap(0x7ffd0b23d000, 18440, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b23d000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7ffd0b751000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7ffd0b750000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 
= 0x7ffd0b87c000
mmap(NULL, 10563168, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0x7ffd0a4c0000
mmap(0x7ffd0ad1d000, 1540096, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x75d000) = 0x7ffd0ad1d000
mmap(0x7ffd0ae95000, 253536, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffd0ae95000
mmap(NULL, 127378, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffd0b85d000
mmap(NULL, 2633944, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0x7ffd0a23c000
mmap(0x7ffd0a4be000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x82000) = 0x7ffd0a4be000
mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffd0a13b000
Process 7697 attached (waiting for parent)
Process 7697 resumed (parent 7696 ready)
[pid  7697] mmap(NULL, 4096, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b87c000
[pid  7697] mmap(NULL, 127378, PROT_READ, MAP_PRIVATE, 3, 0) = 
0x7ffd0b85d000
[pid  7697] mmap(NULL, 2128848, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffd09f33000
[pid  7697] mmap(0x7ffd0a139000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6000) = 0x7ffd0a139000
[pid  7697] mmap(NULL, 1106376, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffd09e24000
[pid  7697] mmap(0x7ffd09f30000, 12288, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xc000) = 0x7ffd09f30000
[pid  7697] mmap(NULL, 1239032, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffd09cf5000
[pid  7697] mmap(0x7ffd09e1d000, 28672, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7ffd09e1d000
[pid  7697] mmap(NULL, 127378, PROT_READ, MAP_PRIVATE, 3, 0) = 
0x7ffd0b85d000
[pid  7697] mmap(NULL, 2202320, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffd09adb000
[pid  7697] mmap(0x7ffd09cf1000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16000) = 0x7ffd09cf1000
[pid  7697] mmap(0x7ffd09cf3000, 6864, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffd09cf3000
[pid  7697] mmap(NULL, 4096, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 
0) = 0x7ffd0b87c000
[pid  7697] mmap(NULL, 4096, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b87b000
[pid  7697] mmap(NULL, 4096, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b87a000
[pid  7697] mmap(NULL, 1090360, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffd099d0000
[pid  7697] mmap(0x7ffd09ad8000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x8000) = 0x7ffd09ad8000
[pid  7697] mmap(0x7ffd09ada000, 824, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffd09ada000
[pid  7697] mmap(NULL, 4096, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b87a000
[pid  7697] mmap(NULL, 127378, PROT_READ, MAP_PRIVATE, 3, 0) = 
0x7ffd0b730000
[pid  7697] mmap(NULL, 2131184, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffd097c7000
[pid  7697] mmap(0x7ffd099ce000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7000) = 0x7ffd099ce000
[pid  7697] mmap(NULL, 127378, PROT_READ, MAP_PRIVATE, 3, 0) = 
0x7ffd0b730000
[pid  7697] mmap(NULL, 2139320, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffd095bc000
[pid  7697] mmap(0x7ffd097c5000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x9000) = 0x7ffd097c5000
[pid  7697] mmap(NULL, 2147720, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffd093af000
[pid  7697] mmap(0x7ffd095ba000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xb000) = 0x7ffd095ba000
[pid  7697] mmap(NULL, 2019, PROT_READ, MAP_SHARED, 3, 0) = 0x7ffd0b87a000
[pid  7697] mmap(NULL, 32768, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0) = 
0x7ffd0b873000
[pid  7697] mmap(0x7ffd0a13b000, 12288, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffd0a13b000
[pid  7697] mmap(NULL, 1126848, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffd0929b000
[pid  7697] mmap(0x7ffd093ab000, 12288, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x10000) = 0x7ffd093ab000
[pid  7697] mmap(0x7ffd093ae000, 448, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffd093ae000
[pid  7697] mmap(NULL, 4096, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b872000
[pid  7697] mmap(NULL, 50331648, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7ffd0629b000
[pid  7697] mmap(0x7ffd0629b000, 2555904, 
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 
0) = 0x7ffd0629b000
[pid  7697] mmap(NULL, 786432, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7ffd0b690000
[pid  7697] mmap(0x7ffd0b690000, 40960, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b690000
[pid  7697] mmap(NULL, 1128267776, PROT_READ|PROT_WRITE|PROT_EXEC,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7ffcc2e9b000
[pid  7697] mmap(NULL, 1128312832, PROT_READ|PROT_WRITE|PROT_EXEC,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7ffcc2e90000
[pid  7697] mmap(NULL, 2207744, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7ffcc2c75000
[pid  7697] mmap(0x7ffcc2e8f000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc2e8f000
[pid  7697] mmap(0x7ffcf17f0000, 21626880, 
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 
0) = 0x7ffcf17f0000
[pid  7697] mmap(0x7ffcc2de9000, 45056, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc2de9000
[pid  7697] mmap(0x7ffcc8290000, 43319296, 
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 
0) = 0x7ffcc8290000
[pid  7697] mmap(NULL, 1355776, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7ffcc2b2a000
[pid  7697] mmap(0x7ffcc2c9f000, 86016, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc2c9f000
[pid  7697] mmap(0x7ffcc2b2a000, 86016, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc2b2a000
[pid  7697] mmap(0x7ffcc2e90000, 21757952, 
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 
0) = 0x7ffcc2e90000
[pid  7697] mmap(NULL, 172032, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7ffcc2b00000
[pid  7697] mmap(0x7ffcc2c75000, 45056, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc2c75000
[pid  7697] mmap(0x7ffcc2b00000, 45056, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc2b00000
[pid  7697] mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffcc29ff000
Process 7698 attached (waiting for parent)
Process 7698 resumed (parent 7697 ready)
[pid  7697] mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffcc28fe000
Process 7699 attached (waiting for parent)
Process 7699 resumed (parent 7697 ready)
[pid  7697] mmap(NULL, 134217728, PROT_NONE, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7ffcba8fe000
[pid  7697] mmap(NULL, 163840, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffcc28d6000
[pid  7697] mmap(NULL, 4096, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b872000
[pid  7697] mmap(NULL, 1661521, PROT_READ, MAP_SHARED, 3, 0x2fb3000) = 
0x7ffcc2740000
[pid  7697] mmap(NULL, 208896, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffcc270d000
[pid  7697] mmap(NULL, 135168, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffcc26ec000
[pid  7697] mmap(NULL, 135168, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffcc26cb000
[pid  7697] mmap(NULL, 135168, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffcc26aa000
[pid  7697] mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffcc25a9000
Process 7700 attached (waiting for parent)
Process 7700 resumed (parent 7697 ready)
[pid  7697] mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffcc24a8000
Process 7701 attached (waiting for parent)
Process 7701 resumed (parent 7697 ready)
[pid  7701] mmap(0x7ffcc24a8000, 12288, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc24a8000
[pid  7697] mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffcc23a7000
Process 7702 attached (waiting for parent)
Process 7702 resumed (parent 7697 ready)
[pid  7702] mmap(0x7ffcc23a7000, 12288, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc23a7000
[pid  7697] mmap(NULL, 4096, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b872000
[pid  7697] mmap(NULL, 256316, PROT_READ, MAP_PRIVATE, 4, 0) = 
0x7ffcc2368000
[pid  7697] mmap(NULL, 26048, PROT_READ, MAP_SHARED, 4, 0) = 0x7ffd0b86c000
[pid  7697] mmap(NULL, 2019, PROT_READ, MAP_SHARED, 4, 0) = 0x7ffd0b86b000
[pid  7697] mmap(NULL, 4096, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffd0b86b000
[pid  7697] mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffcc2267000
Process 7703 attached (waiting for parent)
Process 7703 resumed (parent 7697 ready)
[pid  7703] mmap(0x7ffcc2267000, 12288, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0 <unfinished ...>
[pid  7697] mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffcc2166000
[pid  7703] <... mmap resumed> )        = 0x7ffcc2267000
Process 7704 attached (waiting for parent)
Process 7704 resumed (parent 7697 ready)
[pid  7704] mmap(0x7ffcc2166000, 12288, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc2166000
[pid  7697] mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffcc2065000
Process 7705 attached
[pid  7705] mmap(0x7ffcc2065000, 12288, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc2065000
[pid  7697] mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffcc1f64000
Process 7706 attached (waiting for parent)
Process 7706 resumed (parent 7697 ready)
[pid  7706] mmap(0x7ffcc1f64000, 12288, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffcc1f64000
[pid  7697] mmap(NULL, 1052672, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffcc1e63000
Process 7707 attached (waiting for parent)
Process 7707 resumed (parent 7697 ready)
java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) 64-Bit Server VM (build 14.2-b01, mixed mode)
Process 7707 detached
[pid  7697] mmap(0x7ffd0a13b000, 12288, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7ffd0a13b000
[pid  7703] mmap(0x7ffcc2267000, 12288, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7ffcc2267000
Process 7703 detached
Process 7700 detached
Process 7697 detached
bmaxa@maxa:~$ strace -f -e munmap java -version
munmap(0x7f2e6aa7d000, 127378)          = 0
munmap(0x7f2e6aa9c000, 4096)            = 0
munmap(0x7f149a60a000, 127378)          = 0
munmap(0x7f149a629000, 4096)            = 0
munmap(0x7f149a60a000, 127378)          = 0
Process 7723 attached (waiting for parent)
Process 7723 resumed (parent 7722 ready)
[pid  7723] munmap(0x7f149a629000, 4096) = 0
[pid  7723] munmap(0x7f149a60a000, 127378) = 0
[pid  7723] munmap(0x7f149a60a000, 127378) = 0
[pid  7723] munmap(0x7f149a627000, 4096) = 0
[pid  7723] munmap(0x7f149a627000, 4096) = 0
[pid  7723] munmap(0x7f149a4dd000, 127378) = 0
[pid  7723] munmap(0x7f149a4dd000, 127378) = 0
[pid  7723] munmap(0x7f149a627000, 2019) = 0
[pid  7723] munmap(0x7f149a61f000, 4096) = 0
[pid  7723] munmap(0x7f1451c48000, 1128267776) = 0
[pid  7723] munmap(0x7f1495040000, 32768) = 0
Process 7724 attached (waiting for parent)
Process 7724 resumed (parent 7723 ready)
Process 7725 attached (waiting for parent)
Process 7725 resumed (parent 7723 ready)
[pid  7723] munmap(0x7f149a61f000, 4096) = 0
Process 7726 attached (waiting for parent)
Process 7726 resumed (parent 7723 ready)
Process 7727 attached (waiting for parent)
Process 7727 resumed (parent 7723 ready)
Process 7728 attached (waiting for parent)
Process 7728 resumed (parent 7723 ready)
[pid  7723] munmap(0x7f149a61f000, 4096) = 0
[pid  7723] munmap(0x7f149a618000, 2019) = 0
[pid  7723] munmap(0x7f149a618000, 4096) = 0
Process 7729 attached (waiting for parent)
Process 7729 resumed (parent 7723 ready)
Process 7730 attached (waiting for parent)
Process 7730 resumed (parent 7723 ready)
Process 7731 attached
Process 7732 attached (waiting for parent)
Process 7732 resumed (parent 7723 ready)
Process 7733 attached (waiting for parent)
Process 7733 resumed (parent 7723 ready)
java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) 64-Bit Server VM (build 14.2-b01, mixed mode)
Process 7733 detached
Process 7729 detached
Process 7726 detached
Process 7723 detached
upeek: ptrace(PTRACE_PEEKUSER,7728,120,0): No such process
Process 7728 detached

Why all these mmaps just to write version?

Greets
0
Reply bmaxa209 (243) 2/17/2010 1:43:13 AM

In article <slrnhnlhjq.8a8.apoelstra@localhost.localdomain>,
Andrew Poelstra  <apoelstra@wpsoftware.net> wrote:
>> Upon program exit, the operating system reclaims
>> all memory allocated by the program in one action, and that
>> takes essentially no time at all.

>Perhaps you should write memory managers, if you can really
>reclaim millions of individually allocated blocks in a single
>action.

A general purpose operating system doesn't need to reclaim the
individually allocated blocks, since they were allocated from pages
allocated by the operating system.  It only needs to reclaim those
pages.  What's more, it will do this even if you free the individually
allocated blocks in your program.

-- Richard
-- 
Please remember to mention me / in tapes you leave behind.
0
Reply richard91 (3683) 2/17/2010 1:51:05 AM

In article <evWdnbPgE7XgpebWnZ2dnUVZ7qidnZ2d@bt.com>,
Richard Heathfield  <rjh@see.sig.invalid> wrote:

>In practice, I do see something wrong with relying on that behaviour, 
>and my opinion is based on experience of a (fairly large - several 
>hundred thousand lines) program that did rely on that behaviour. I 
>didn't write it, but I did have to help fix it.
[...]
>main()
>{
>   for(big_old_loop)
>   {
>     func();
>   }
>}

I have written programs which had this problem.  On the other hand, I
have written many more which were never modified in that way.

Overall, would I have saved or wasted time by planning ahead for
something which usually didn't happen?  I can't be certain.  But I's
much rather do the work when it's needed than when it's not.

And of course, you often have a pretty good idea whether a particular
bit of code is likely to be reused in that way.

-- Richard
-- 
Please remember to mention me / in tapes you leave behind.
0
Reply richard91 (3683) 2/17/2010 2:06:05 AM

On 2010-02-17, Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
> In article <slrnhnlhjq.8a8.apoelstra@localhost.localdomain>,
> Andrew Poelstra  <apoelstra@wpsoftware.net> wrote:
>>> Upon program exit, the operating system reclaims
>>> all memory allocated by the program in one action, and that
>>> takes essentially no time at all.
>
>>Perhaps you should write memory managers, if you can really
>>reclaim millions of individually allocated blocks in a single
>>action.
>
> A general purpose operating system doesn't need to reclaim the
> individually allocated blocks, since they were allocated from pages
> allocated by the operating system.  It only needs to reclaim those
> pages.  What's more, it will do this even if you free the individually
> allocated blocks in your program.

Only a complete fool argues against a statement about ``one action'',
without any agreed-upon definition of ``action'' anywhere in sight.

What is an action? One machine instruction? One system call?

An atomic transaction across fifteen servers can be called ``action''
according to some view of a system.
0
Reply kkylheku (2499) 2/17/2010 2:11:58 AM

On 2010-02-17, Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
> In article <slrnhnlhjq.8a8.apoelstra@localhost.localdomain>,
> Andrew Poelstra  <apoelstra@wpsoftware.net> wrote:
>>> Upon program exit, the operating system reclaims
>>> all memory allocated by the program in one action, and that
>>> takes essentially no time at all.
>
>>Perhaps you should write memory managers, if you can really
>>reclaim millions of individually allocated blocks in a single
>>action.
>
> A general purpose operating system doesn't need to reclaim the
> individually allocated blocks, since they were allocated from pages
> allocated by the operating system.  It only needs to reclaim those
> pages.  What's more, it will do this even if you free the individually
> allocated blocks in your program.
>

To yourself and Kaz, I was wrong on this point. Thanks for
explaining it. Unfortunately I haven't taken any operating
systems courses yet, so my experience with memory managers
has been limited to brief overviews in Knuth and assembler
manuals.

Having said that, I still don't think it's good to rely on
this operating system behavior. It seems to be unnecessary
unportability. Plus, it is so much easier to use valgrind.


0
Reply apoelstra (387) 2/17/2010 2:37:19 AM

On Feb 16, 6:49=A0pm, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-02-16, ImpalerCore <jadil...@gmail.com> wrote:
>
> > Do you differentiate between detecting memory that is considered a
> > leak versus memory that you allow the OS to cleanup?
>
> I certainly do.
>
> > I would think it
> > would be a benefit to know if the application *can* shutdown cleanly
> > so that memory leaks could be determined. =A0Whether you consider that
> > time-wasting is up to you. =A0Does that attitude also extend to library
> > development?
>
> It depends a lot on circumstances. =A0Generally, at the least, I'd expect=
 to
> know which pieces of storage I'm allocating that I expect to still be the=
re
> at the end of execution.

Then why did I get counted off for forgetting to free memory in my
data structures class in college?  I wish I knew this argument back
then :)

> > What's your opinion on other I/O sources? =A0Do you bother to close
> > files, sockets, database connections, or do you also depend on the
> > underlying architecture to "do the right thing"?
>
> That also depends quite a bit on circumstances. =A0I usually close files,=
 but
> there have been exceptions.
>
> As an example, I have a hunk of code I maintain right now, in which a few
> files are opened, and a few resources allocated, which are not released o=
n
> exit -- because this hunk of code is intercepting the actions of other
> programs, and does not necessarily know about their exits. =A0More import=
antly,
> it is fairly trivial to prove that even if I tried to intercept their exi=
ts,
> I could not do so safely. =A0Either I would deallocate my resources at a =
time
> when the other program could then perform actions which still required th=
em,
> or I would have to leave them allocated until a point at which nothing wa=
s
> going to transfer control back to me. =A0Can't win.
>
> > I'm biased this way since I have not encountered a situation where the
> > shutdown time/complexity is an issue, but maybe you have.
>
> I have. =A0I once had a program which took over five seconds to exit on w=
hat
> was, at the time, a very fast machine. =A0In that case, I swapped a key d=
ata
> structure from an array of pointers to an array of objects, and it got fa=
ster
> by, well, about a factor of eighty, which was good enough.

I don't have a problem with the general idea of letting the OS reclaim
memory, but I don't have the experience to know how and when to make
the decision.  If it takes 1, 5, or 30 seconds to end the program,
should that be a sign to just throw the hands up in the air to give it
to the OS to handle?  Is there some other process really needing that
extra 5 seconds?  Are users complaining about 5 seconds to close the
program?  Is it that it costs more to develop the code to free
everything as efficiently, so it's cheaper to just let the OS handle
it?

> -s
> --
> Copyright 2010, all wrongs reversed. =A0Peter Seebach / usenet-nos...@see=
bs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny picturesht=
tp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

0
Reply jadill33 (201) 2/17/2010 3:17:24 AM

Richard Heathfield wrote:
) In practice, I do see something wrong with relying on that behaviour, 
) and my opinion is based on experience of a (fairly large - several 
) hundred thousand lines) program that did rely on that behaviour. I 
) didn't write it, but I did have to help fix it.
)
) In bare outline, it worked like this:
)
) main()
) {
)    lots_of_functions_that_do_not_bother_to_clean_up();
) }
)
) And then, one day, it got maintained, as programs do:
)
) func()
) {
)    lots_of_functions_that_do_not_bother_to_clean_up();
) }
)
) main()
) {
)    for(big_old_loop)
)    {
)      func();
)    }
) }
)
) Suddenly we had a huge maintenance problem on our hands because the 
) original crew were too lazy to manage memory properly. This cost a 
) significant amount of time (and therefore money) to fix, because the 
) knowledge of the right points at which to free up the many and varied 
) allocations had been discarded, and now had to be reacquired.

- What was the probability at the time of writing that such a change
  was ever going to happen ?
  (As a rough estimate, how many such programs have been written other than
   this one which had to be changed)
  (Let's say one in M)
- What was the relation between the time it would have cost the original
  programmers to free all the resources correctly, and the time it did cost
  to go back and then free all the resources correctly afterward ?
  (Let's say one in N)

I find it likely that M is significantly larger than N, in which case
the original decision was correct, because it actually saved time,
even in the long run.

Or, to put it in some randomly picked numbers:

Suppose that program was one in a hundred programs that were written
without regard for free()ing every resource.  Then, afterward you had
to go back and fix everything, which took ten times as long as it would
have for the original programmers.  For that one program.  In total,
it would have taken the original programmers ten times as long as it
took now for all those programs combined.


And, of course, there may have been more pragmatic solutions available,
such as the extra layer of memory management mentioned elsethread, or
some kind of loop that fork()s, runs the process in the child fork,
and wait()s in the parent fork for the child to finish before starting
the next iteration.


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply willem7123 (117) 2/17/2010 8:24:52 AM

Andrew Poelstra wrote:
> On 2010-02-16, Seebs <usenet-nospam@seebs.net> wrote:
> > On 2010-02-16, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> >> ...or this one? The OS, if it frees your memory, needs just
> >> as much CPU time as your code would, had you chosen to make
> >> it portable to machines who are not your mother.
> >
> > Not generally true.
> >
> > Imagine that I have allocated a linked list of a million nodes, each
> > pointing to 1024 bytes of data.  On a typical malloc implementation,
> > freeing these will result in no fewer than two million separate operations,
> > each of which may also result in complicated operations as the library
> > consolidates free space, etcetera.
> >
> > The operating system will simply mark my pages unused -- which it has to do
> > whether or not I've freed them in terms of the library operation.
> >
> > The operating system can do it faster because it doesn't need to care about
> > the internals and bookkeeping of the malloc arena.
> >
>
> But you would need to have found a gigabyte of contiguous memory
> dedicated to your program for this to be simple - otherwise you
> would be in memory space also used by other applications, and
> bookkeeping does matter.

Not necessarily. Most of the modern operating systems implement some
form of paging and virtual memory. Unused pages are simply paged out
to disk and mapped back to RAM only when accessed.

Under these types of systems, deallocating memory got from malloc
simply makes little or no difference to the memory management of the
OS. OTOH the standard library allocator can hand them out to future
requests, so it's usually a good idea to free() memory when you no
longer need it.

But from the OS's point of view, unused or stale pages are unmapped
from real addresses and written to disk, the space reclaimed can now
be mapped to other pages of other processes, or the current one. And
in systems like Linux, virtual memory allocations even greater than
available free physical memory are granted, with the system mapping
pages to physical RAM only on first use, or killing a random process
if it cannot.

I guess this is one reason why large programs like Firefox allocate
massive amounts of virtual memory when starting up, confident that a
majority of it will not actually reside in RAM. The concept of virtual
memory has made life easier for multitasking systems, but it does mean
that programs have gotten into the habit of allocating far more memory
than necessary, or in not deallocating when done.

Finally, when the process terminates, normally or abnormally, with or
without explicitly calling free() for each malloc(), all pages for the
process are simply reclaimed. Privileged processes can of course, play
with the system in ways normal processes can't.

But it's still a good idea to deallocate resources when you're
finished with them, unless doing so would not be worth it. And to know
it it'd be worth it, we need to know about other considerations. But
IMHO, manually deallocating memory before exit should be the rule
rather than the exception.
0
Reply santosh.k83 (3969) 2/17/2010 8:45:07 AM

Seebs wrote:
> On 2010-02-17, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> main()
>> {
>>    lots_of_functions_that_do_not_bother_to_clean_up();
>> }
>>
>> And then, one day, it got maintained, as programs do:
>>
>> func()
>> {
>>    lots_of_functions_that_do_not_bother_to_clean_up();
>> }
> 
> Ahh, I see.
> 
> I don't do it that way.  The only time I abandon cleanup is when there
> is no reason to allocate something again once it's allocated -- if I
> thought a new pass might allocate the same resources, then I would indeed
> free them up.

So you'd have caused us the same problem that $PROGRAMMING_TEAM did. 
After all, at the time they wrote the code, they had no reason to 
suspect a new pass; this was not added until some time after completion 
of the original program.

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 2/17/2010 9:26:06 AM

On 17 Feb, 02:37, Andrew Poelstra <apoels...@localhost.localdomain>
wrote:
> On 2010-02-17, Richard Tobin <rich...@cogsci.ed.ac.uk> wrote:
> > In article <slrnhnlhjq.8a8.apoels...@localhost.localdomain>,
> > Andrew Poelstra =A0<apoels...@wpsoftware.net> wrote:

> >>> Upon program exit, the operating system reclaims
> >>> all memory allocated by the program in one action, and that
> >>> takes essentially no time at all.
>
> >>Perhaps you should write memory managers, if you can really
> >>reclaim millions of individually allocated blocks in a single
> >>action.

to the OS it isn't millions of objects but a single lump of contiguous
memory. Underneath malloc() there is likely a call to the OS to
allocate more memory for the process (effectivly the current running
program). Unix traditionally called this pbrk(). Often this "heap"
area was a contiguous lump of memory that could be simply returned to
the OSs free memory pool at the end. This is all slightly more
complicated with virtual memory, paging etc.

You might have a point with things that aren't just memory such as
Windows's GDI objects or Pens. Older versions of Windows were
notorious for leaking such resources.


> > A general purpose operating system doesn't need to reclaim the
> > individually allocated blocks, since they were allocated from pages
> > allocated by the operating system. =A0It only needs to reclaim those
> > pages. =A0What's more, it will do this even if you free the individuall=
y
> > allocated blocks in your program.
>
> To yourself and Kaz, I was wrong on this point. Thanks for
> explaining it. Unfortunately I haven't taken any operating
> systems courses yet, so my experience with memory managers
> has been limited to brief overviews in Knuth and assembler
> manuals.

the last chapter of K&R discusses how C might be implemented on Unix.
That might be interesting.


> Having said that, I still don't think it's good to rely on
> this operating system behavior. It seems to be unnecessary
> unportability. Plus, it is so much easier to use valgrind.

freeing millions of objects really can be expensive. I think a modern
OS that didn't free memory properly when a process terminated would be
pretty broken!

on the other hand it gives a slightly queasy feeling not match every
malloc() with a free()!


--
"Pluralitas non est ponenda sine neccesitate"
"plurality should not be posited without necessity."
 William of Ockham (ca.1285-1349)

0
Reply nick_keighley_nospam (4574) 2/17/2010 9:38:47 AM

Willem wrote:
> Richard Heathfield wrote:
<snip>

> )
> ) Suddenly we had a huge maintenance problem on our hands because the 
> ) original crew were too lazy to manage memory properly. This cost a 
> ) significant amount of time (and therefore money) to fix, because the 
> ) knowledge of the right points at which to free up the many and varied 
> ) allocations had been discarded, and now had to be reacquired.
> 
> - What was the probability at the time of writing that such a change
>   was ever going to happen ?

Between 0 and 1, obviously, but apart from that, unknown.

>   (As a rough estimate, how many such programs have been written other than
>    this one which had to be changed)
>   (Let's say one in M)
> - What was the relation between the time it would have cost the original
>   programmers to free all the resources correctly, and the time it did cost
>   to go back and then free all the resources correctly afterward ?
>   (Let's say one in N)
> 
> I find it likely that M is significantly larger than N, in which case
> the original decision was correct, because it actually saved time,
> even in the long run.

I disagree, partly because this program was so very large that the cost 
of fixing it up was commensurately large, but also on the general 
principle that useful software tends to get used, and really useful 
software gets used in ever new ways, so it makes sense to build 
reliability in at the start. I started writing an excellent analogy 
here, but it turned out to be a stupid analogy, so I've spared you. :-)

> 
> Or, to put it in some randomly picked numbers:
> 
> Suppose that program was one in a hundred programs that were written
> without regard for free()ing every resource.  Then, afterward you had
> to go back and fix everything, which took ten times as long as it would
> have for the original programmers.  For that one program.  In total,
> it would have taken the original programmers ten times as long as it
> took now for all those programs combined.

No, because that program in itself was probably larger than all other 
programs produced by the same team in the previous decade or so, put 
together.

> And, of course, there may have been more pragmatic solutions available,
> such as the extra layer of memory management mentioned elsethread, or
> some kind of loop that fork()s, runs the process in the child fork,
> and wait()s in the parent fork for the child to finish before starting
> the next iteration.

I'd love to see a fork() that works on MVS and Windows 3.11 (the two 
target platforms). :-)

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 2/17/2010 9:45:45 AM

On 16 Feb, 18:50, jacob navia <ja...@spamsink.net> wrote:
> Andrew Poelstra a =E9crit :
> > On 2010-02-16, jacob navia <ja...@spamsink.net> wrote:
> >> Andrew Poelstra a =E9crit :
> >>> On 2010-02-16, Hyman Rosen <hyro...@mail.com> wrote:
> >>>> On 2/14/2010 6:22 PM, Ertugrul S=F6ylemez wrote:
> >>>>> p...@informatimago.com (Pascal J. Bourguignon) wrote:


> >>>>>> Perhaps today, for short lived C processes, you just don't have to
> >>>>>> care about free anymore. =A0Just malloc, and exit.
>
> >>>>> This reasoning is used by many PHP programmers today. =A0It's one r=
eason
> >>>>> why PHP programs are so error-prone and why PHP errors are often ha=
rd to
> >>>>> find. =A0There is no excuse for unfreed resources, particularly in
> >>>>> languages, which are unsafe by nature, like C and PHP. =A0It _will_=
 get
> >>>>> you into trouble sooner or later.
>
> >>>> There is generally no need to free resources just before
> >>>> program exit, because the operating system will do that
> >>> What basis do you have for this absurd claim...
>
> >> "Absurd claim"
>
> >> ALL OS do that. If not, they would run a single leaking program and
> >> would die immediately.
>
> > Not immediately.
>
> ????
>
> > And if this was an embedded system, eventually
> > the watchdog would kick and the programmer would (hopefully)
> > realize that his code was buggy and needed fixing.

I think Mr Poelstra and Mr Navia are in different programming
universes. Jacob is using desk top systems with decent modern
operating systems (or windows :-) ) and lots and lots of memory.
Whilst Andrew is on semi-embedded systems with run time systems that
barely qualify as an OS. Its slightly worrying that he's doing this
bare back stuff without knowing much about OSs...


> the code is not buggy.

if my set top box rebooted every 15 minutes due to a memory leak I'd
call that buggy.


> >> I have never seen an OS that did not do that.
>
> > Again, in embedded systems many OS's choose not to support
> > bad programming. There are no users downloading garbage
> > from the Internet and blithely expecting it to run despite
> > barely being compilable.
>
> OK. In your pet os (with lowercase) a program that has
> a memory leak will bring the whole system down.
>
> GREAT SYSTEM!
>
> >>>> for you - a program which spends a bunch of time freeing
> >>>> every allocated object and then exits has just wasted all
> >>> ...or this one? The OS, if it frees your memory, needs just
> >>> as much CPU time as your code would,
>
> >> No, in most cases it will use a single free() call
> >> since all memory allocated for a process will be in
> >> a single heap.
>
> > But in "most cases" there is so little memory allocated
> > that the equivalent free() calls will take practically
> > zero time anyway. In the cases that a ton of memory is
> > used, then the OS has its work set out for it whether or
> > not the code is explicitly calling free().
>
> you have no idea how modern OSes work apparently


I'm slightly surprised that an embedded system with bare OS support
does any mallocing at all!


0
Reply nick_keighley_nospam (4574) 2/17/2010 9:49:18 AM

On 16 Feb, 20:42, Ertugrul S=F6ylemez <e...@ertes.de> wrote:

> In times, where you measure processor cycles in GHz and available memory
> in GiB and where the complexity of applications gets huge, it's very
> dangerous to go with program exiting (!) performance. =A0In general you
> will prefer correctness and predictability over a slightly faster
> process exit.

so that's why it takes so bloody long to shutdown my machine!
0
Reply nick_keighley_nospam (4574) 2/17/2010 9:52:10 AM

In article <20100216151044.582@gmail.com>, Kaz Kylheku <kkylheku@gmail.com> writes:

> Programmers who get paid for a living want their programs to be portable in a
> way that is /economically/ relevant, balanced with other requirements.  

Agree completely.


> Maximal portability, the kind where we pretend we write a single body of
> source code without conditionl compilation while pretending we programming
> for an incapable, broken platform, is only an obsession of a few dull minds.

Please don't. This is also an economically feasible approach, only with
very different economic factors.


> That should come as no surprise: it requires a lower level reasoning than
> doing a crossword puzzle from the newspaper.

Ignoring for a moment that this is a factually incorrect deliberate
offense, isn't it the general understanding that reasoning and code and
development processes that require less mental strain are easier to keep
bug-free?

Cheers,
lacos
0
Reply lacos (176) 2/17/2010 9:55:15 AM

On 17 Feb, 03:17, ImpalerCore <jadil...@gmail.com> wrote:
> On Feb 16, 6:49=A0pm, Seebs <usenet-nos...@seebs.net> wrote:
> > On 2010-02-16, ImpalerCore <jadil...@gmail.com> wrote:


> > > Do you differentiate between detecting memory that is considered a
> > > leak versus memory that you allow the OS to cleanup?
>
> > I certainly do.
>
> > > I would think it
> > > would be a benefit to know if the application *can* shutdown cleanly
> > > so that memory leaks could be determined. =A0Whether you consider tha=
t
> > > time-wasting is up to you. =A0Does that attitude also extend to libra=
ry
> > > development?
>
> > It depends a lot on circumstances. =A0Generally, at the least, I'd expe=
ct to
> > know which pieces of storage I'm allocating that I expect to still be t=
here
> > at the end of execution.
>
> Then why did I get counted off for forgetting to free memory in my
> data structures class in college? =A0I wish I knew this argument back
> then :)

you have to play be their rules.  As you might have noted there are
strong opinions on both sides!  Proper cleanup makes it easier to spot
unintentional memory leaks. Leaving the OS to cleanup is quicker.
Perhaps you could have a fast shutdown version and a clean everything
up version. Or mark items that really should be alive at program exit
time.

<snip>

> > > I'm biased this way since I have not encountered a situation where th=
e
> > > shutdown time/complexity is an issue, but maybe you have.

long shutdown times irritate me.


> > I have. =A0I once had a program which took over five seconds to exit on=
 what
> > was, at the time, a very fast machine.

I dream of 5s shutdown times... 5s is practically instantaneous!


> >=A0In that case, I swapped a key data
> > structure from an array of pointers to an array of objects, and it got =
faster
> > by, well, about a factor of eighty, which was good enough.
>
> I don't have a problem with the general idea of letting the OS reclaim
> memory, but I don't have the experience to know how and when to make
> the decision. =A0If it takes 1, 5, or 30 seconds to end the program,
> should that be a sign to just throw the hands up in the air to give it
> to the OS to handle? =A0Is there some other process really needing that
> extra 5 seconds? =A0Are users complaining about 5 seconds to close the
> program? =A0Is it that it costs more to develop the code to free
> everything as efficiently, so it's cheaper to just let the OS handle
> it?

there is no simple answer. It depends on the environment, the
application, the user community. If the progranm is supposed to "run
for ever" the fact that it takes 30-40s to shutdown may not matter. If
it's a unix filter I'd be unimpressed with anything other than than
"instant" shutdown.


--
some things have to be believed to be seen
-- hoyle
0
Reply nick_keighley_nospam (4574) 2/17/2010 10:05:08 AM

Nick Keighley wrote:
> On 16 Feb, 20:42, Ertugrul S�ylemez <e...@ertes.de> wrote:
> 
>> In times, where you measure processor cycles in GHz and available memory
>> in GiB and where the complexity of applications gets huge, it's very
>> dangerous to go with program exiting (!) performance.  In general you
>> will prefer correctness and predictability over a slightly faster
>> process exit.
> 
> so that's why it takes so bloody long to shutdown my machine!
Well, let me explain real world example.

You have php script that prepares dat for some other process about 20 
and more hours. That's slow, similar optimized program in C woulnd't
take more than 20-30 minutes estimate.
But since C is not safe language and actually no one
knows it because it is obsolete, let use hadoop
to distribute script to cluster of servers and make it faster.
That is how are things are done in *real world* today!
0
Reply bmaxa209 (243) 2/17/2010 10:06:39 AM

On 16 Feb, 23:35, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-02-16, Ertugrul S=F6ylemez <e...@ertes.de> wrote:

> > That's also the reason I suggest freeing all of the allocated memory
> > before exiting. =A0If you don't, there is a closing tag missing in your
> > program pattern. =A0When you restructure your program, you might
> > accidentally forget that missing closing tag and introduce memory leaks=
..
> > You know how difficult it can be to find memory leaks, if you ever
> > notice them at all.

if you don't notice them they don't matter!

> I actually have a memory debugger I wrote to find them. =A0As you might e=
xpect,
> it couldn't solve the actual problem.

I too have spent many a happy hour hunting memory leaks.

> Because, technically, it wasn't a leak -- when I went through freeing
> everything at the end of program execution, all the allocated space got
> freed. =A0However. =A0During execution, it was possible for a particular =
object
> to end up with a linked list of unbounded size of allocated things that i=
t
> maintained as internal state, which were neither used nor exposed to any
> other interface, making it very hard to find them -- and since it did fre=
e
> them correctly on exit, there was no memory leak.

mine actually were leaks. The memory concerned no longer had any
references to it and wouldn't be freed on shutdown.

Every time a timer was started a tiny little bit of memory went
missing... Over a period of weeks this begins to matter!
0
Reply nick_keighley_nospam (4574) 2/17/2010 10:15:25 AM

On 17 Feb, 01:13, Richard Heathfield <r...@see.sig.invalid> wrote:
> Kaz Kylheku wrote:
> > ["Followup-To:" header set to comp.lang.c.]
> > On 2010-02-17, Richard Heathfield <r...@see.sig.invalid> wrote:

> >> Suddenly we had a huge maintenance problem on our hands because the
> >> original crew were too lazy to manage memory properly. This cost a
> >> significant amount of time (and therefore money) to fix, because the
> >> knowledge of the right points at which to free up the many and varied
> >> allocations had been discarded, and now had to be reacquired.
>
> > You wasted your time and money only because you didn't think of redirec=
ting
> > the functions to use an alternate malloc-like API which keeps track of =
the
> > allocations, such that they can be freed with an additional call when f=
unc()
> > exits:
>
> It's true that we didn't think of such a scheme. Even if we had, though,
> either we'd have had to visit every malloc and free to replace them with
> the meta-memory-management function calls,

I've done this with a perl script.


> or we'd have had to redefine
> malloc(). The latter would have been unacceptable, I think. The former
> may have saved us a little time, though, if we had thought of it.
>
> But the time saving would have been optimum if the original programmer
> had done his job correctly.

http://en.wikipedia.org/wiki/You_ain't_gonna_need_it


> > The original programmer did the right thing by not wasting time on this
> > problem. =A0The new use case was not a functional requirement for that =
program.
>
> I am reminded of the student who, when asked to write a program to add
> two numbers together and print the result, asked the lecturer "which two
> numbers should I add?"


:-)
0
Reply nick_keighley_nospam (4574) 2/17/2010 10:19:30 AM

On Feb 16, 5:45=A0pm, Andrew Poelstra <apoels...@localhost.localdomain>
wrote:
> On 2010-02-16, Hyman Rosen <hyro...@mail.com> wrote:
>
> > On 2/14/2010 6:22 PM, Ertugrul S=F6ylemez wrote:
> >> p...@informatimago.com (Pascal J. Bourguignon) wrote:
> >>> Perhaps today, for short lived C processes, you just don't have to
> >>> care about free anymore. =A0Just malloc, and exit.
>
> >> This reasoning is used by many PHP programmers today. =A0It's one reas=
on
> >> why PHP programs are so error-prone and why PHP errors are often hard =
to
> >> find. =A0There is no excuse for unfreed resources, particularly in
> >> languages, which are unsafe by nature, like C and PHP. =A0It _will_ ge=
t
> >> you into trouble sooner or later.
>
> > There is generally no need to free resources just before
> > program exit, because the operating system will do that
>
> What basis do you have for this absurd claim...

Hardly absurd. Most OSs will reclaim all the user-space memory
previously assigned to a process, when it exits. One exception I can
think of is DOS with its TSR syscall. I also imagine embedded OSs that
don't implement virtual memory *might* also suffer from this, but that
doesn't make the claim absurd at all. It's actually very logical for
your garden variety current desktop OS (think Linux, Windows, etc).

> > for you - a program which spends a bunch of time freeing
> > every allocated object and then exits has just wasted all
>
> ...or this one? The OS, if it frees your memory, needs just
> as much CPU time as your code would, had you chosen to make
> it portable to machines who are not your mother.

The OS won't call free(). It doesn't do the same bookkeeping as a
process. Are you trying to be intentionally absurd?

> Allocators allocate. To ascribe anything more to them is
> presumptuous and unjustified.

What about bookkeeping? Error checking? What about memory
rearrangement to alleviate fragmentation? Are those unjustified? Or
does your generic term for "allocate" imply all of these?
0
Reply electricdelta (73) 2/17/2010 10:57:01 AM

Branimir Maksimovic a �crit :
> Nick Keighley wrote:
>> On 16 Feb, 20:42, Ertugrul S�ylemez <e...@ertes.de> wrote:
>>
>>> In times, where you measure processor cycles in GHz and available memory
>>> in GiB and where the complexity of applications gets huge, it's very
>>> dangerous to go with program exiting (!) performance.  In general you
>>> will prefer correctness and predictability over a slightly faster
>>> process exit.
>>
>> so that's why it takes so bloody long to shutdown my machine!
> Well, let me explain real world example.
> 
> You have php script that prepares dat for some other process about 20 
> and more hours. That's slow, similar optimized program in C woulnd't
> take more than 20-30 minutes estimate.
> But since C is not safe language and actually no one
> knows it because it is obsolete, let use hadoop
> to distribute script to cluster of servers and make it faster.
> That is how are things are done in *real world* today!

Please do not speak about "the real world" here.

People here are living in systems that do not even cleanup
when a process stops, and insist that all programs in C should
be written ready to be ported to such "advanced" systems.

They want to perpetuate the notion that C is obsolete. It is only
THEY that are obsolete; but... never mind.
0
Reply jacob31 (869) 2/17/2010 12:34:44 PM

ImpalerCore <jadill33@gmail.com> writes:

> On Feb 16, 6:49 pm, Seebs <usenet-nos...@seebs.net> wrote:
>> On 2010-02-16, ImpalerCore <jadil...@gmail.com> wrote:
>>
>> > Do you differentiate between detecting memory that is considered a
>> > leak versus memory that you allow the OS to cleanup?
>>
>> I certainly do.
>>
>> > I would think it
>> > would be a benefit to know if the application *can* shutdown cleanly
>> > so that memory leaks could be determined.  Whether you consider that
>> > time-wasting is up to you.  Does that attitude also extend to library
>> > development?
>>
>> It depends a lot on circumstances.  Generally, at the least, I'd expect to
>> know which pieces of storage I'm allocating that I expect to still be there
>> at the end of execution.
>
> Then why did I get counted off for forgetting to free memory in my
> data structures class in college?  I wish I knew this argument back
> then :)

OK, smiley noted, but that is not a comparable situation.  Freeing up
the memory used by a data structure is a proper part of its
implementation and testing that such clean-up functions work is a
proper part of the exercise.

In practise, I'd write the memory freeing code (unless, for some
reason, it really was very complex to write) and simply exclude the
free-ing up code (#ifdef TIDY_UP) prior to exit if I found it was
taking too long.

PS, yes I've used an OS that does not free memory on program exit:
TRIPOS (and yes, there was a good reason for the OS to be designed
that way).
-- 
Ben.
0
Reply ben.usenet (6515) 2/17/2010 12:49:56 PM

On 2/16/2010 5:45 PM, ImpalerCore wrote:
> Care to elaborate?

It's exactly what I've said - it was an application that
was taking forever to exit because on exit it was cleaning
up all of its memory. We changed it not to do that, and
then it exited quickly.
0
Reply hyrosen (1792) 2/17/2010 2:08:11 PM

On 2/16/2010 6:10 PM, Kaz Kylheku wrote:
> Not only is it compute-time wasting, it is developer-time wasting
> to develop it.

Actually, it's the other way around - you have to exercise a little
care not to get the cleanup, because these days memory allocations
are wrapped in objects with destructors.
0
Reply hyrosen (1792) 2/17/2010 2:11:31 PM

On Tue, 16 Feb 2010 18:38:40 +0100, jacob navia <jacob@spamsink.net>
wrote:

>Andrew Poelstra a �crit :
>> On 2010-02-16, Hyman Rosen <hyrosen@mail.com> wrote:
>>> On 2/14/2010 6:22 PM, Ertugrul S�ylemez wrote:
>>>> pjb@informatimago.com (Pascal J. Bourguignon) wrote:
>>>>> Perhaps today, for short lived C processes, you just don't have to
>>>>> care about free anymore.  Just malloc, and exit.
>>>> This reasoning is used by many PHP programmers today.  It's one reason
>>>> why PHP programs are so error-prone and why PHP errors are often hard to
>>>> find.  There is no excuse for unfreed resources, particularly in
>>>> languages, which are unsafe by nature, like C and PHP.  It _will_ get
>>>> you into trouble sooner or later.
>>> There is generally no need to free resources just before
>>> program exit, because the operating system will do that
>> 
>> What basis do you have for this absurd claim...
>
>
>"Absurd claim"
>
>ALL OS do that. If not, they would run a single leaking program and 
>would die immediately.
>
>I have never seen an OS that did not do that.

IIRC, an early version of AmigaDos did require a process to free all
its allocated memory before termination.  Any memory not freed was NOT
returned to the OS.  AmigaDos development machines crashed a LOT!

IMHO that was severely broken behavior, but it existed nonetheless.

-- 
Bob Doherty
0
Reply rdoherty21 (3) 2/17/2010 2:15:26 PM

On Feb 17, 9:08=A0am, Hyman Rosen <hyro...@mail.com> wrote:
> On 2/16/2010 5:45 PM, ImpalerCore wrote:
>
> > Care to elaborate?
>
> It's exactly what I've said - it was an application that
> was taking forever to exit because on exit it was cleaning
> up all of its memory. We changed it not to do that, and
> then it exited quickly.

What I meant is what is the threshold that made you decide to rely on
the OS to clean up (how long was your "forever")?  1, 5, 10, 60 second
shutdown?
0
Reply jadill33 (201) 2/17/2010 2:27:02 PM

In article <20100216163757.121@gmail.com>, Kaz Kylheku <kkylheku@gmail.com> writes:

> You wasted your time and money only because you didn't think of redirecting
> the functions to use an alternate malloc-like API which keeps track of the
> allocations, such that they can be freed with an additional call when func()
> exits:
> 
>  main()
>  {
>    for(big_old_loop)
>    {
>       heap *h = heap_create();
>       func(h);
>       heap_dispose(h);
>    }
>  }

> [...]

> calls like
> 
>   obj *p = (obj *) malloc(sizeof *p);
> 
> are replaced with:
> 
>   obj *p = (obj *) heap_alloc(my_heap, sizeof *p);
> 
> or through a wrapper which looks like malloc.
> 
> This is not a ``huge maintenance problem''.


I think it can be more complex than that. The malloc() family consists
(under SUS) of at least malloc(), calloc(), realloc(), free(),
posix_memalign(). Add the historical functions valloc() and memalign(), then
perhaps anonymous (and even file-backed) mmap()'s and whatever else.
Several other functions allocate memory or other resources, like
catopen(), iconv_open() and regcomp().

exit() does a lot of things in kernel space, "standard library space"
and "user program space".

http://www.opengroup.org/onlinepubs/000095399/functions/exit.html

When the body of main() is moved into a loop, free()'ing what was
malloc()'d is only one thing that must be "emulated" manually before the
next iteration commences, if the original programmer didn't deal with it
him- or herself.

Setup functionality must be extracted anyway, but if the programmer was
liberal in the "meat" of the code with releasing resources, it may be
very hard to register all the corresponding allocations in a bottom-up
way -- there are many types of allocations, also implicit allocations
like strdup(). (Perhaps strdup() should be considered a member of the
malloc() family.)

I'd guess in an "elegant" C++ program, the root(s) of the object graph
are auto objects in main() and static objects scattered all over the
place. Their destructors will be called in the end, and that should
result in an avalanche of destructors. Of course one can call _exit() by
hand, but I still reckon this final cascade is common in C++ programs,
and that it doesn't cause many problems. Nor should its C equivalent.

Cheers,
lacos
0
Reply lacos (176) 2/17/2010 2:40:37 PM

On 2/17/2010 9:27 AM, ImpalerCore wrote:
> What I meant is what is the threshold that made you decide to rely on
> the OS to clean up (how long was your "forever")?  1, 5, 10, 60 second
> shutdown?

So long that it was noticeable and annoying.
It doesn't matter exactly how long that was.
0
Reply hyrosen (1792) 2/17/2010 2:51:10 PM

On 2/17/2010 9:27 AM, ImpalerCore wrote:
 > What I meant is what is the threshold that made you decide to rely on
 > the OS to clean up (how long was your "forever")?  1, 5, 10, 60 second
 > shutdown?

So long that it was noticeable and annoying.
It doesn't matter exactly how long that was.
0
Reply hyrosen (1792) 2/17/2010 2:54:38 PM

In article <20100216180746.241@gmail.com>,
Kaz Kylheku  <kkylheku@gmail.com> wrote:

>Only a complete fool argues against a statement about ``one action'',
>without any agreed-upon definition of ``action'' anywhere in sight.

My aim was to enlighten the poster, not to win an argument by
pedantry.  If that's being a complete fool, I can put up with it.

-- Richard
-- 
Please remember to mention me / in tapes you leave behind.
0
Reply richard91 (3683) 2/17/2010 3:00:41 PM

On 2/16/2010 7:46 PM, Kaz Kylheku wrote:
>   main()
>   {
>     for(big_old_loop)
>     {
>        heap *h = heap_create();
>        func(h);
>        heap_dispose(h);
>     }
>   }

Unless you're very careful, this is an anti-pattern,
and will cause difficult to diagnose errors for this
common singleton pattern:

     char *getGlobalFoozleBuffer()
     {
         static char *buf = calloc(147, 13);
         return buf;
     }

This is also another example of a sort of memory allocation
which is not, and need not be, freed by the program before
it exits.
0
Reply hyrosen (1792) 2/17/2010 3:00:58 PM

On 2/16/2010 7:46 PM, Kaz Kylheku wrote:
 >   main()
 >   {
 >     for(big_old_loop)
 >     {
 >        heap *h = heap_create();
 >        func(h);
 >        heap_dispose(h);
 >     }
 >   }

Unless you're very careful, this is an anti-pattern,
and will cause difficult to diagnose errors for this
common singleton pattern:

     char *getGlobalFoozleBuffer()
     {
         static char *buf = calloc(147, 13);
         return buf;
     }

This is also another example of a sort of memory allocation
which is not, and need not be, freed by the program before
it exits.
0
Reply hyrosen (1792) 2/17/2010 3:03:33 PM

On 2/16/2010 7:46 PM, Kaz Kylheku wrote:
 >   main()
 >   {
 >     for(big_old_loop)
 >     {
 >        heap *h = heap_create();
 >        func(h);
 >        heap_dispose(h);
 >     }
 >   }

Unless you're very careful, this is an anti-pattern,
and will cause difficult to diagnose errors for this
common singleton pattern:

     char *getGlobalFoozleBuffer()
     {
         static char *buf = calloc(147, 13);
         return buf;
     }

This is also another example of a sort of memory allocation
which is not, and need not be, freed by the program before
it exits.
0
Reply hyrosen (1792) 2/17/2010 3:06:16 PM

Richard Tobin wrote:
> In article <20100216180746.241@gmail.com>,
> Kaz Kylheku  <kkylheku@gmail.com> wrote:
> 
>> Only a complete fool argues against a statement about ``one action'',
>> without any agreed-upon definition of ``action'' anywhere in sight.
> 
> My aim was to enlighten the poster, not to win an argument by
> pedantry.  If that's being a complete fool, I can put up with it.

Only a complete fool makes blanket statements about what only a complete 
fool would do, so I wouldn't pay too much attention if I were you.

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 2/17/2010 3:07:43 PM

Hyman Rosen <hyrosen@mail.com> writes:

> On 2/16/2010 10:45 AM, Andrew Poelstra wrote:
>> On 2010-02-16, Hyman Rosen<hyrosen@mail.com>  wrote:
>>> There is generally no need to free resources just before
>>> program exit, because the operating system will do that
>>
>> What basis do you have for this absurd claim...
>
> Experience. Logic.
>
>>> for you - a program which spends a bunch of time freeing
>>> every allocated object and then exits has just wasted all
>>
>> ...or this one? The OS, if it frees your memory, needs just
>> as much CPU time as your code would, had you chosen to make
>> it portable to machines who are not your mother.
>
> No. A program which insists on freeing its allocated memory
> does so by going through each allocated object individually
> freeing it. This can involve large amounts of time when the
> program has allocated millions of objects in its data
> structures. Upon program exit, the operating system reclaims
> all memory allocated by the program in one action, and that
> takes essentially no time at all.
>
> This is not even to mention that when a program frees allocated
> memory through 'free', it is usually doing nothing but placing
> that memory back onto an internal data structure so that it may
> be allocated again. It is seldom returned to the operating system
> because it was not allocated that way; allocators request large
> blocks and break them up internally to the program.


What is worse, it makes the program touch all the memory blocs,
therefore fetching all of them from the swap file!

So instead of just exiting and have one swap block write (to free the
swap used by that process), you now have 4 GB of swap out to free memory
for the loading of 4 GB of swap in, just to "free" that memory before
exiting, and then of course, reading again the 4GB swapped out
previous...

Hence my use of kill -9 for "applications" that don't quit when I tell
them to quit...

-- 
__Pascal Bourguignon__
http://www.informatimago.com
0
Reply pjb (7646) 2/17/2010 3:53:07 PM

Hyman Rosen <hyrosen@mail.com> writes:
> On 2/16/2010 6:10 PM, Kaz Kylheku wrote:
>> Not only is it compute-time wasting, it is developer-time wasting
>> to develop it.
>
> Actually, it's the other way around - you have to exercise a little
> care not to get the cleanup, because these days memory allocations
> are wrapped in objects with destructors.

Not in this newsgroup.  (I'm posting from comp.lang.c.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 2/17/2010 4:21:44 PM

Hyman Rosen <hyrosen@mail.com> writes:
> On 2/16/2010 7:46 PM, Kaz Kylheku wrote:
>>   main()
>>   {
>>     for(big_old_loop)
>>     {
>>        heap *h = heap_create();
>>        func(h);
>>        heap_dispose(h);
>>     }
>>   }
>
> Unless you're very careful,

So be very careful.

>                             this is an anti-pattern,
> and will cause difficult to diagnose errors for this
> common singleton pattern:
>
>     char *getGlobalFoozleBuffer()
>     {
>         static char *buf = calloc(147, 13);
>         return buf;
>     }

Why is buf static?

I think what Kaz had in mind is that any memory that needs to be
deallocated on each iteration of the loop is allocated, not via
malloc and friends, but by some other routines that use the "heap"
object created by heap_create().  Since getGlobalFoozleBuffer
calls calloc() directly, the allocated memory won't be affected
by heap_dispose().

The tricky part is knowing which allocations need to survive
throughout the program execution, and which need to be cleaned up
on each iteration of the outer loop.  And this can be extended to
multiple levels; the above main() might eventually become a function
in a larger program.

> This is also another example of a sort of memory allocation
> which is not, and need not be, freed by the program before
> it exits.

Maybe.  It depends on how global the FoozleBuffer really is.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 2/17/2010 4:45:43 PM

On 2010-02-17, Richard Heathfield <rjh@see.sig.invalid> wrote:
> So you'd have caused us the same problem that $PROGRAMMING_TEAM did. 
> After all, at the time they wrote the code, they had no reason to 
> suspect a new pass; this was not added until some time after completion 
> of the original program.

Maybe.  My guess is that I wouldn't have, because the unfreed allocations
would all be of the form:

	if (!table)
		table = malloc(...);

and adding passes would have no effect.  The only cases I can think of where
I have unconditional allocations which aren't freed, they lead to something
to the effect of:
	execv(...);
	fprintf(stderr, "exec failed: %s\naborting.\n", strerror(errno));
	exit(EXIT_FAILURE);

Or, probably in some cases, there's a single giant object with a foo_free()
defined which you could free at the end of each pass.

Hmm.  Okay, I found an exception.  I have a typical Unix-style filter
lying around which does not deallocate its buffer and list of offsets into
the buffer.  On the other hand, because it's a filter, it's *already*
looping, so it wouldn't make much sense to try to invoke it in a loop.  If
you did need to, though, it'd be pretty easy.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/17/2010 5:09:04 PM

On 2010-02-17, Ersek, Laszlo <lacos@ludens.elte.hu> wrote:
>> Maximal portability, the kind where we pretend we write a single body of
>> source code without conditionl compilation while pretending we programming
>> for an incapable, broken platform, is only an obsession of a few dull minds.
>
> Please don't. This is also an economically feasible approach, only with
> very different economic factors.

Sure, you can always put together a portability programming tournament,
where everyone pays to enter, and the winner fetches a monetary prize.

The same economic factors as in poker, golf, competitive road running,
etc.

In actual software, maximal portabilty is the enemy of portability.

>> That should come as no surprise: it requires a lower level reasoning than
>> doing a crossword puzzle from the newspaper.
>
> Ignoring for a moment that this is a factually incorrect deliberate
> offense, isn't it the general understanding that reasoning and code and
> development processes that require less mental strain are easier to keep
> bug-free?

I didn't say anything about less work.  A lower /level/ of reasoning
doesn't translate to less work.

For instance, throughout this thread you've been advocating the addition
of /completely unnecessary/ code (bearing unnecessary risk) to a program
for the sake of portability.

How can it ever be less straining to add more code, compared to
not adding it at all?

Any monkey can read a couple of ISO standards a few times over again and
learn to spot nonportability in code.

``Hey look, that text stream was closed and a few lines before it, it's
clear that the last character written wasn't a newline! I'm so smart!''
0
Reply kkylheku (2499) 2/17/2010 6:00:55 PM

Richard Heathfield wrote:
> Richard Tobin wrote:
>> In article <20100216180746.241@gmail.com>,
>> Kaz Kylheku  <kkylheku@gmail.com> wrote:
>>
>>> Only a complete fool argues against a statement about ``one action'',
>>> without any agreed-upon definition of ``action'' anywhere in sight.
>>
>> My aim was to enlighten the poster, not to win an argument by
>> pedantry.  If that's being a complete fool, I can put up with it.
> 
> Only a complete fool makes blanket statements about what only a complete 
> fool would do, so I wouldn't pay too much attention if I were you.

There are a number of people who I think of as complete fools, who take 
every opportunity to paint Richard Heathfield with the brush of 
"complete fool", but since I regard them as complete fools, I can 
completely ignore their attempts to undermine Richard's credibility.

To find Richard calling himself a complete fool is rather puzzling, as 
he otherwise scores fairly high on my credibility meter. If I believe 
him, then he has no credibility and if he has no credibility then I 
don't believe him. But if I don't believe him then he does have 
credibility, so I should believe him.

Help! The paradox is melting my brain!

-- 
Usenet is an opportunity to empathize with people. If you can't
feel the other person's pain, then you're not inflicting enough.
         -- Eb Oesch
0
Reply eternity (1) 2/17/2010 6:20:05 PM

Zarquon wrote:
> Richard Heathfield wrote:
>> Richard Tobin wrote:
>>> In article <20100216180746.241@gmail.com>,
>>> Kaz Kylheku  <kkylheku@gmail.com> wrote:
>>>
>>>> Only a complete fool argues against a statement about ``one action'',
>>>> without any agreed-upon definition of ``action'' anywhere in sight.
>>>
>>> My aim was to enlighten the poster, not to win an argument by
>>> pedantry.  If that's being a complete fool, I can put up with it.
>>
>> Only a complete fool makes blanket statements about what only a 
>> complete fool would do, so I wouldn't pay too much attention if I were 
>> you.
> 
> There are a number of people who I think of as complete fools, who take 
> every opportunity to paint Richard Heathfield with the brush of 
> "complete fool", but since I regard them as complete fools, I can 
> completely ignore their attempts to undermine Richard's credibility.

Just to set the record straight, I don't truly think of Kaz as a 
complete fool. In fact, I regard him very highly, although (like mine) 
his mastery of tact and diplomacy still has a few weak spots. That is 
not to say that I always agree with his technical opinions, but where we 
disagree I generally find myself looking hard at my own views, because 
Kaz has a good track record of being right.

> To find Richard calling himself a complete fool is rather puzzling,

My sense of humour is indeed rather strange.

<snip>

> Help! The paradox is melting my brain!

Easily fixed - just accept that it's a paradox, and therefore an 
inadequate description of the real situation.

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 2/17/2010 6:24:31 PM

["Followup-To:" header set to comp.lang.c.]
On 2010-02-17, Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
> In article <20100216180746.241@gmail.com>,
> Kaz Kylheku  <kkylheku@gmail.com> wrote:
>
>>Only a complete fool argues against a statement about ``one action'',
>>without any agreed-upon definition of ``action'' anywhere in sight.
>
> My aim was to enlighten the poster, not to win an argument by
> pedantry.  If that's being a complete fool, I can put up with it.

Sorry, I that wasn't aimed at you. :)
0
Reply kkylheku (2499) 2/17/2010 6:34:30 PM

Kaz Kylheku <kkylheku@gmail.com> wrote:

> On 2010-02-16, Ertugrul S=C3=B6ylemez <es@ertes.de> wrote:
> > Hyman Rosen <hyrosen@mail.com> wrote:
> >
> >> On 2/16/2010 3:42 PM, Ertugrul S=C3=B6ylemez wrote:
> >> > It is a bug, but some people tolerate it, some don't.  What the
> >> > operating system does here is not called resource management, but
> >> > fault tolerance.  It should be designed not to fail on
> >> > programming errors.
> >>
> >> What a bizarre notion. What happens to the resources of a program
> >> when the program exits is defined by the operating system. Relying
> >> on OS-defined behavior in your program is not an error. Performing
> >> time-wasting activity on abstract grounds of illusory correctness,
> >> on the other hand, is an error.
> >
> > You're showing that you are an irresponsible programmer.  C and
> > Cobol are about the only languages in wide-spread use, which even
> > allow that kind of carelessness.  Modern languages are even designed
> > to prevent you from being stupid.  But obviously you want to be
> > stupid.
>
> What modern languages would those be? I suspect you could not name one
> such that you are not wrong.

All languages with an automatic garbage collector.  There are even
languages, which implement that "tag stack" I mentioned earlier
directly, like C# with its 'using' directive.


> > Relying on operating system fault tolerance is wrong and most good
>
> It's not fault tolerance but resource management. You are pitifully
> wrong in your other posting.
>
> Relying on this is no more wrong than relying on a TCP/IP stack,
> graphics display, or DMA transfers.

TCP/IP stack, graphics display and DMA transfers are functionality.
What you can "resource management" prevents the system from crashing,
just because some programmers write wrong code.  That's not
functionality, it's fault tolerance.


> > It's no
> > programmers will agree, at the very least because they want their
> > programs to be portable
>
> Programmers who get paid for a living want their programs to be
> portable in a way that is /economically/ relevant, balanced with other
> requirements.
>
> Maximal portability, the kind where we pretend we write a single body
> of source code without conditionl compilation while pretending we
> programming for an incapable, broken platform, is only an obsession of
> a few dull minds.

What the hell is wrong with freeing resources?  It takes twenty seconds
to write the code to do it.  The code itself uses at most one or two
seconds to execute and guarantees correctness.

We all know how well most commercial programs work.  If that is your
"enconomically relevant, balanced" portability, then commercial
application development is in a bad state.

Serious programmers won't even argue about this topic.  We're talking
about something as trivial as freeing allocated resources.  He will just
do it and that's it.  After all, that's what he has learned from books
and school anyway.


> > Modularity is the key to maintainability, and if you disagree here,
> > you're just ridiculous and nobody will take you seriously anyway.
>
> Without automatic storage managament, there is no real modularity.
> Modules are coupled together by the distributed responsibility of
> memory management.  It creeps into all the interfaces: who allocates
> what and who will free it.
>
> It's laughable to advocate explicit storage deallocation and
> modularity in the same breath.

Indeed.  Having a system, which guarantees correctness, is important in
such a setting.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/17/2010 6:46:35 PM

On 2010-02-17, Ertugrul S�ylemez <es@ertes.de> wrote:
> What the hell is wrong with freeing resources?  It takes twenty seconds
> to write the code to do it.  The code itself uses at most one or two
> seconds to execute and guarantees correctness.

Well, no.

1.  It doesn't guarantee correctness.  I already provided an example where
it did not guarantee correctness, because a program could run out of memory
if it ran long enough, even though at any given point, if it exited, it
would free everything.
2.  It can take a lot more than twenty seconds to write the code to do it.
3.  It can take a lot more than one or two seconds to execute, especially
on slower hardware.

There exist cases where there are good reasons not to do it.  They may be
specialized cases, they may not be all that common...

Here's the thing.  If you want to argue that it's a good idea, and should be
assumed as a default strategy and used until someone has a concrete and
specific reason not to do it, great!  I agree totally.

When you start making blanket assertions, or calling programs which rely on
a 100% documented and guaranteed aspect of their operating environment
"incorrect", though, you undermine your position.  The net result is that not
only are people not persuaded of what you're saying, they're persuaded against
the general practice of freeing allocated resources, because they conclude
that the people advocating it are fanatics who don't understand engineering
tradeoffs.

> Serious programmers won't even argue about this topic.

Does preemptively insulting people for disagreeing with you usually work
in your culture?  In mine it's often taken to be a sign of lacking persuasive
arguments.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/17/2010 6:53:55 PM

Seebs <usenet-nospam@seebs.net> writes:
> On 2010-02-17, Ertugrul Söylemez <es@ertes.de> wrote:
>> What the hell is wrong with freeing resources?  It takes twenty seconds
>> to write the code to do it.  The code itself uses at most one or two
>> seconds to execute and guarantees correctness.
>
> Well, no.
>
> 1.  It doesn't guarantee correctness.  I already provided an example where
> it did not guarantee correctness, because a program could run out of memory
> if it ran long enough, even though at any given point, if it exited, it
> would free everything.
> 2.  It can take a lot more than twenty seconds to write the code to do it.
> 3.  It can take a lot more than one or two seconds to execute, especially
> on slower hardware.

4. Even if it takes only one or two seconds, that overhead might
be unacceptable.  If my text editor takes one or two seconds to
terminate after I tell it to exit, I'll be annoyed.  If a command
that I execute a few hundred times in a loop takes one or two seconds
to exit, I'll probably have to find a different way to accomplish
my task.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 2/17/2010 7:38:59 PM

On 2010-02-17, Keith Thompson <kst-u@mib.org> wrote:
> Hyman Rosen <hyrosen@mail.com> writes:
>> On 2/16/2010 7:46 PM, Kaz Kylheku wrote:
>>>   main()
>>>   {
>>>     for(big_old_loop)
>>>     {
>>>        heap *h = heap_create();
>>>        func(h);
>>>        heap_dispose(h);
>>>     }
>>>   }
>>
>> Unless you're very careful,
>
> So be very careful.
>
>>                             this is an anti-pattern,
>> and will cause difficult to diagnose errors for this
>> common singleton pattern:
>>
>>     char *getGlobalFoozleBuffer()
>>     {
>>         static char *buf = calloc(147, 13);
>>         return buf;
>>     }
>
> Why is buf static?

Because this is a singleton pattern; each call to this function
is expected to yield the same object.

> I think what Kaz had in mind is that any memory that needs to be
> deallocated on each iteration of the loop is allocated, not via
> malloc and friends, but by some other routines that use the "heap"
> object created by heap_create().  Since getGlobalFoozleBuffer
> calls calloc() directly, the allocated memory won't be affected
> by heap_dispose().

But originally, /all/ functions call the allocator directly, just
like this function.  When we are refactoring the program to use the heap
allocator we have to distinguish this case, and perhaps have it do this:

  static char *buf = heap_calloc(global_heap, 147, 13);

But this is a simple case where the data flow is simple: the source of
the dynamic object and its destination static variable are in the same
full expression. This is not always the case in a real program.  The
calloc call may be in some generic routine that is called (perhaps
through a number of levels of call nesting), such that its return value
is sometimes stored in a static variable and sometimes not.

So then the whole function chain needs to pass down the allocation
context.

Finding such cases in a large program is difficult, and so this can
add significant risk.

This boils down to the problem of various degrees of incompleteness of
the simulation of re-running a program.  To run a C program, we must
initialize its static variables to their correct intial values specified
in the source code (among lots of other things). Since we have not done
that, we get the old values of the static variables, which may contain
dangling pointers.

The first solution I might reach for to solve this would be dynamic linking,
which is available on a number of important platforms, and provides
reinitialization of statics (if you unload a library and then re-load,
it gets new statics which are properly initialized). On platforms that
support dynamic linking, it can be considered the preferred tool
for turning standa-alone programs into components of other programs.
There is likely going to be some considerable overhead in doing the
unload and reloading, since it involves mapping and unmapping memory.

A less easy, though more portable solution which has other advantages
too, is to identify the static variables of program foo and factor them
out into a ``struct foo_globals''.  Then we can initialize them before
re-running the program. This is a lot of work, but at least it's
largely mechanical: looking for all file scope and block scope static
definitions.

A much less portable solution, though seemingly easy, would be to get
help from a scriptable linker like GNU ld.  The static objects in
program foo could be put into custom .foo.bss and .foo.data section. On
program startup, we stash a copy of .foo.data somewhere. Prior to each
call to the foo_main, we reinitialize the .foo.data section with the
stashed copy, and clear .foo.bss to all zero bits.
0
Reply kkylheku (2499) 2/17/2010 7:46:16 PM

On 2010-02-17, Ertugrul Söylemez <es@ertes.de> wrote:
> Kaz Kylheku <kkylheku@gmail.com> wrote:
>
>> On 2010-02-16, Ertugrul Söylemez <es@ertes.de> wrote:
>> > Hyman Rosen <hyrosen@mail.com> wrote:
>> >
>> >> On 2/16/2010 3:42 PM, Ertugrul Söylemez wrote:
>> >> > It is a bug, but some people tolerate it, some don't.  What the
>> >> > operating system does here is not called resource management, but
>> >> > fault tolerance.  It should be designed not to fail on
>> >> > programming errors.
>> >>
>> >> What a bizarre notion. What happens to the resources of a program
>> >> when the program exits is defined by the operating system. Relying
>> >> on OS-defined behavior in your program is not an error. Performing
>> >> time-wasting activity on abstract grounds of illusory correctness,
>> >> on the other hand, is an error.
>> >
>> > You're showing that you are an irresponsible programmer.  C and
>> > Cobol are about the only languages in wide-spread use, which even
>> > allow that kind of carelessness.  Modern languages are even designed
>> > to prevent you from being stupid.  But obviously you want to be
>> > stupid.
>>
>> What modern languages would those be? I suspect you could not name one
>> such that you are not wrong.
>
> All languages with an automatic garbage collector.  There are even
> languages, which implement that "tag stack" I mentioned earlier
> directly, like C# with its 'using' directive.

You're confusing ``storage managed language'' with ``language
which requires all resources to be released when the program
terminates''.

I can think of several storage-managed languages which neglect this
requirement (/and/ do not provide any way for the program to
implement its own cleanup!)

>> > Relying on operating system fault tolerance is wrong and most good
>>
>> It's not fault tolerance but resource management. You are pitifully
>> wrong in your other posting.
>>
>> Relying on this is no more wrong than relying on a TCP/IP stack,
>> graphics display, or DMA transfers.
>
> TCP/IP stack, graphics display and DMA transfers are functionality.
> What you can "resource management" prevents the system from crashing,
> just because some programmers write wrong code.  That's not
> functionality, it's fault tolerance.

Yet you advocate garbage collection. Garbage collection can also be
regarded as not storage management, but fault tolerance, which
prevents the system from crashing in the face of ``bad'' programs.

Procewss clean up is a coarsely grained form of garbage collection.
A process has certain private resources (no other process has access
to them). So when a process goes away, those resources become
garbage.

My troll detector is starting to go off at this point;
repeated contradictions like this can only be planted.
0
Reply kkylheku (2499) 2/17/2010 8:32:57 PM

On Feb 17, 1:53=A0pm, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-02-17, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
>
> > What the hell is wrong with freeing resources? =A0It takes twenty secon=
ds
> > to write the code to do it. =A0The code itself uses at most one or two
> > seconds to execute and guarantees correctness.
>
> Well, no.
>
> 1. =A0It doesn't guarantee correctness. =A0I already provided an example =
where
> it did not guarantee correctness, because a program could run out of memo=
ry
> if it ran long enough, even though at any given point, if it exited, it
> would free everything.
> 2. =A0It can take a lot more than twenty seconds to write the code to do =
it.
> 3. =A0It can take a lot more than one or two seconds to execute, especial=
ly
> on slower hardware.
>
> There exist cases where there are good reasons not to do it. =A0They may =
be
> specialized cases, they may not be all that common...
>
> Here's the thing. =A0If you want to argue that it's a good idea, and shou=
ld be
> assumed as a default strategy and used until someone has a concrete and
> specific reason not to do it, great! =A0I agree totally.
>
> When you start making blanket assertions, or calling programs which rely =
on
> a 100% documented and guaranteed aspect of their operating environment
> "incorrect", though, you undermine your position. =A0The net result is th=
at not
> only are people not persuaded of what you're saying, they're persuaded ag=
ainst
> the general practice of freeing allocated resources, because they conclud=
e
> that the people advocating it are fanatics who don't understand engineeri=
ng
> tradeoffs.

To me, this argument advocates the practice of not explicitly freeing
allocated resources since

1. Deallocating memory at the 'free' level is slower, and gets worse
the complexity increases.
2. It costs more to code it properly and verify.
3. Many target OS handle this condition out of the box.

Why should using "free" be the default strategy when the OS does it
"better"?  Why should I spend hours writing and testing manually
freeing resources at the end of any application, when I can get the
above benefits of letting the OS handle it?  (Again, I'm not referring
to avoiding freeing resources at all within the normal run of a
program, just at the end of the application.)

If you started a new project where all the target OS have this
feature, why bother explicitly freeing memory resources at all?

> > Serious programmers won't even argue about this topic.
>
> Does preemptively insulting people for disagreeing with you usually work
> in your culture? =A0In mine it's often taken to be a sign of lacking pers=
uasive
> arguments.
>
> -s
> --
> Copyright 2010, all wrongs reversed. =A0Peter Seebach / usenet-nos...@see=
bs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny picturesht=
tp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

0
Reply jadill33 (201) 2/17/2010 8:38:05 PM

On 2010-02-17, Seebs <usenet-nospam@seebs.net> wrote:
> On 2010-02-17, Ertugrul Söylemez <es@ertes.de> wrote:
>> Serious programmers won't even argue about this topic.
>
> Does preemptively insulting people for disagreeing with you usually work
> in your culture?  In mine it's often taken to be a sign of lacking persuasive
> arguments.

Note that ``about this topic'' means either side. This is a
clear ``I am trolling'' signal for the astute readers.
0
Reply kkylheku (2499) 2/17/2010 8:41:10 PM

On 2010-02-17, ImpalerCore <jadill33@gmail.com> wrote:
> To me, this argument advocates the practice of not explicitly freeing
> allocated resources since

It is intended to advocate the practice of *thinking* about it.

> Why should using "free" be the default strategy when the OS does it
> "better"?

1.  It doesn't.  For anything which happens more than once during a run,
a memory leak can mean that your program fails from running out of memory
before the OS cleans it up.
2.  It is *in general* a good way to make sure you've correctly understood
your design and don't have any fundamental memory-management bugs.

> Why should I spend hours writing and testing manually
> freeing resources at the end of any application, when I can get the
> above benefits of letting the OS handle it?  (Again, I'm not referring
> to avoiding freeing resources at all within the normal run of a
> program, just at the end of the application.)

Consistency.  If I free things when I'm done with them regardless of
whether I'm done with them for this loop or for this program, my code
will be more consistent and easier to follow.

> If you started a new project where all the target OS have this
> feature, why bother explicitly freeing memory resources at all?

Because the vast majority of my allocations are in processes which occur
repeatedly.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/17/2010 8:55:52 PM

On 2010-02-17, Kaz Kylheku <kkylheku@gmail.com> wrote:
> On 2010-02-17, Seebs <usenet-nospam@seebs.net> wrote:
>> On 2010-02-17, Ertugrul S�ylemez <es@ertes.de> wrote:
>>> Serious programmers won't even argue about this topic.

>> Does preemptively insulting people for disagreeing with you usually work
>> in your culture?  In mine it's often taken to be a sign of lacking persuasive
>> arguments.

> Note that ``about this topic'' means either side. This is a
> clear ``I am trolling'' signal for the astute readers.

That could be.  With the .de address, I was also thinking it might be that
the choice of preposition wasn't quite idiomatic, since that happens a lot
between German and English.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/17/2010 8:56:41 PM

Kaz Kylheku <kkylheku@gmail.com> writes:
> On 2010-02-17, Keith Thompson <kst-u@mib.org> wrote:
>> Hyman Rosen <hyrosen@mail.com> writes:
[...]
>>>     char *getGlobalFoozleBuffer()
>>>     {
>>>         static char *buf = calloc(147, 13);
>>>         return buf;
>>>     }
>>
>> Why is buf static?
>
> Because this is a singleton pattern; each call to this function
> is expected to yield the same object.

I had assumed that calloc() would be called each time
getGlobalFoozleBuffer() is called, and that the above was equivalent
to:

    char *getGlobalFoozleBuffer()
    {
        return calloc(147, 13);
    }

But in fact the above isn't even legal in C.  The initializer for an
object with static storage duration must be constant (C99 6.7.8p4).

<OT>The rules are are different in C++.</OT>

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 2/17/2010 9:23:55 PM

In article <JwTen.36395$aU4.17600@newsfe13.iad>,
Hyman Rosen  <hyrosen@mail.com> wrote:
>Unless you're very careful, this is an anti-pattern,
>and will cause difficult to diagnose errors for this
>common singleton pattern:
>
>     char *getGlobalFoozleBuffer()
>     {
>         static char *buf = calloc(147, 13);
>         return buf;
>     }
>
>This is also another example of a sort of memory allocation
>which is not, and need not be, freed by the program before
>it exits.

Your code fragment leaks memory if getGlobalFoozleBuffer() is called
more than once; I thinks this makes more sense:

    char *getGlobalFoozleBuffer()
    {
        static char *buf; /* initially NULL */
        if (buf == NULL)
          buf = calloc(147, 13);
        return buf;
    }
0
Reply ike5 (222) 2/17/2010 9:31:59 PM

On Feb 17, 3:55=A0pm, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-02-17, ImpalerCore <jadil...@gmail.com> wrote:
>
> > To me, this argument advocates the practice of not explicitly freeing
> > allocated resources since
>
> It is intended to advocate the practice of *thinking* about it.

Well, you've been successful in that aspect.

> > Why should using "free" be the default strategy when the OS does it
> > "better"?
>
> 1. =A0It doesn't. =A0For anything which happens more than once during a r=
un,
> a memory leak can mean that your program fails from running out of memory
> before the OS cleans it up.
> 2. =A0It is *in general* a good way to make sure you've correctly underst=
ood
> your design and don't have any fundamental memory-management bugs.

I agree, and I've spent a lot of time trying to verify memory
management correctness, and I still run into little bugs.  I just
started testing my library code with an allocator that fails and
returns NULL on some nth iteration, and it has led to several seg
faults and requiring another rethink of my implementation.

> > Why should I spend hours writing and testing manually
> > freeing resources at the end of any application, when I can get the
> > above benefits of letting the OS handle it? =A0(Again, I'm not referrin=
g
> > to avoiding freeing resources at all within the normal run of a
> > program, just at the end of the application.)
>
> Consistency. =A0If I free things when I'm done with them regardless of
> whether I'm done with them for this loop or for this program, my code
> will be more consistent and easier to follow.
>
> > If you started a new project where all the target OS have this
> > feature, why bother explicitly freeing memory resources at all?
>
> Because the vast majority of my allocations are in processes which occur
> repeatedly.

Do you agree with, as a rule of thumb, that a developer should
implement a manual free of an application to verify correctness, and
if some metric isn't met (shutdown time,lifetime issues), shortcut the
system and let the OS release the resources.

From the tone of some of the other posters, I (probably incorrectly)
perceived that they think that implementing a "manual free" version is
a waste of time given an application with enough complexity.

Best regards,
John D.

> -s
> --
> Copyright 2010, all wrongs reversed. =A0Peter Seebach / usenet-nos...@see=
bs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny picturesht=
tp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply jadill33 (201) 2/17/2010 9:39:40 PM

On 2010-02-17, ImpalerCore <jadill33@gmail.com> wrote:
> Do you agree with, as a rule of thumb, that a developer should
> implement a manual free of an application to verify correctness, and
> if some metric isn't met (shutdown time,lifetime issues), shortcut the
> system and let the OS release the resources.

As a rule of thumb, yes.

> From the tone of some of the other posters, I (probably incorrectly)
> perceived that they think that implementing a "manual free" version is
> a waste of time given an application with enough complexity.

It might be.  There might be cases where I'd look at it and conclude that
it wasn't appropriate, and there are cases where an API makes freeing
impossible.  For instance, the POSIX getenv/setenv has a design such that it
MUST leak memory in at least some cases.  Similarly, argument lists allocated
before calling exec() can't be freed.

Freeing everything you allocate is a very good rule of thumb, but not a very
good bit of absolute dogmatism.  Similarly, it's a great idea to write
portably *when possible*, but if your task is inherently non-portable, it may
not make any sense to try to make it portable.  I usually find that writing
clean and portable code for as much of it as possible is still rewarding,
but "portable" can be a bit abstract.  A function to manipulate the contents
of a "struct stat" really has no reason to try to be portable outside of
Unix-like environments.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/17/2010 10:34:20 PM

In article <20100217194635.3a5ca88e@tritium.streitmacht.eu>,
Ertugrul Söylemez  <es@ertes.de> wrote:

>> What modern languages would those be? I suspect you could not name one
>> such that you are not wrong.

>All languages with an automatic garbage collector.

I have used many implementations of such languages that did not
perform a garbage collection before exiting.  Objects that happened to
be live when the program exited were therefore not freed within the
program.

-- Richard
-- 
Please remember to mention me / in tapes you leave behind.
0
Reply richard91 (3683) 2/18/2010 1:15:19 AM

"Hyman Rosen" <hyrosen@mail.com> ha scritto nel messaggio
news:IBTen.36397$aU4.28478@newsfe13.iad...
>     char *getGlobalFoozleBuffer()
>     {
>         static char *buf = calloc(147, 13);
>         return buf;
>     }
>
> This is also another example of a sort of memory allocation
> which is not, and need not be, freed by the program before
> it exits.

why? it is memory of the heap used, so if you not free it:
a memory leak.
in some place
first of the end of the program
there is the need of   free(buf)



0
Reply io_x 2/18/2010 7:26:00 AM

"io_x" <a@b.c.invalid> ha scritto nel messaggio
news:4b7abf16$0$1120$4fafbaef@reader2.news.tin.it...
>
> "Andrew Poelstra" <apoelstra@localhost.localdomain> ha scritto nel messaggio
> news:slrnhnlfa4.6sc.apoelstra@localhost.localdomain...
>>> for you - a program which spends a bunch of time freeing
>>> every allocated object and then exits has just wasted all
>>
>> ...or this one? The OS, if it frees your memory, needs just
>> as much CPU time as your code would,
>
> this should be wrong, bacause OS should free
> all big arrays of chars
> that give to the malloc function (heap) instead you
> have to free all the sub arrays of these big arrays

i don't say it is the way i would follow;
i would free each bit of data mallockked
for see if there are memory leak or out of bound.

But in case of error or abort i would
1) Print some message where is the error
2) close all FILE open
3) Free memory of the big arrays
   of the malloc-heap
4) exit() function of the compiler or if it is not
   possibile [example in .dlls when .dll are in .asm]
   the exit() function of the OS

>> had you chosen to make
>> it portable to machines who are not your mother.
>>
>>> of that time. It's important to free resources which can
>>> be allocated in an unbounded fashion. That is, a program
>>> should act like a garbage collector - unreachable objects
>>> must be reclaimed, but reachable ones don't need to be.
>>
>
>




0
Reply io_x 2/18/2010 7:26:04 AM

On 17 Feb, 18:46, Ertugrul S=F6ylemez <e...@ertes.de> wrote:

<snip>

> What the hell is wrong with freeing resources? =A0It takes twenty seconds
> to write the code to do it. =A0The code itself uses at most one or two
> seconds to execute and guarantees correctness.

it only "guarantees correctness" because you defined correctness as
"freeing all resources at the end of a program".

> We all know how well most commercial programs work. =A0If that is your
> "enconomically relevant, balanced" portability, then commercial
> application development is in a bad state.
>
> Serious programmers won't even argue about this topic. =A0

so you, me, Seebs and Kaz aren't serious programmers?


<snip>
0
Reply nick_keighley_nospam (4574) 2/18/2010 8:32:22 AM

On 02/16/2010 09:53 AM, Seebs wrote:
> Have you never seen Windows 3.1 or DOS?  Both had C implementations where
> malloc() could reserve memory that lived past program termination.

I only used Turbo C on MSDOS, but as far as I know, all malloc()d memory
was reclaimed unless you exited via the keep() call, which was basically
"terminate and stay resident". You'd tell keep() how much memory (in
16-byte "paragraphs") needed to stay resident, including the code
size... keep() was unaware of which memory had been malloc()d or was on
the stack or was in the code segment or anything.

So it wasn't so much a function of malloc(), as it was telling the OS
what you wanted it to do after the program terminated. Though I'm not
certain, I believe keep() used the MSDOS memory allocation calls to
reserve the memory from the OS.

FWIW,
-Beej
0
Reply beej (444) 2/18/2010 9:37:46 AM

In article <20100217094624.22@gmail.com>,
Kaz Kylheku <kkylheku@gmail.com> writes:

> On 2010-02-17, Ersek, Laszlo <lacos@ludens.elte.hu> wrote:
> >> Maximal portability, the kind where we pretend we write a single
> >> body of source code without conditionl compilation while pretending
> >> we programming for an incapable, broken platform, is only an
> >> obsession of a few dull minds.
> >
> > Please don't. This is also an economically feasible approach, only
> > with very different economic factors.
>
> Sure, you can always put together a portability programming
> tournament, where everyone pays to enter, and the winner fetches a
> monetary prize.
>
> The same economic factors as in poker, golf, competitive road running,
> etc.
>
> In actual software, maximal portabilty is the enemy of portability.

If you are paid in the long term to bring the best out of any given
platform, then again to port the program to the next platform when your
customer changes platforms, then you are right, and I think I agreed to
that before.

OTOH, you seem to say that software developed along different incentives
is not "actual software". I disagree. If it gets the work done reliably,
it is actual software.


(I'm reordering quotes from your post.)

> For instance, throughout this thread you've been advocating the
> addition of /completely unnecessary/ code (bearing unnecessary risk)
> to a program for the sake of portability.

For my situation that code (and the resultant risk, if any) is not
unnecessary and not without reward. I think that code will help me catch
bugs and/or, as you say, increase portability. Portability helps me
decrease the burden of maintenance and porting, and after correctness,
that's my ultimate incentive -- no maintenance. I code C first and
foremost to scratch my itches -- I'm currently hired to do different
stuff. I don't want to hack continuously on those solutions as I wander
among platforms. If somebody else finds my code useful, that's a big
additional benefit, but not the main motive.

I will sacrifice performance and features in order to deliver myself
from maintenance burden. You might implement tight loops in assembly, or
use platform-specific async IO. I will write that loop in C and call
select() and be done with it. I will reimplement functionality that has
been available in glibc for 15 years, if it's not in SUSv2. You might
come up with an elaborate subsytem of pluggable modules to collect /
mask implementation-dependent behavior. I'd rather avoid (work around)
such behavior.

If I had to ask the sysadmin to install a new version of gcc, because my
code relies on gcc extensions, or had to install gcc under $HOME myself,
that would immediately qualify as a lost cause. While in a professional,
paid-for setting, nothing should be more natural (ideally) than choosing
your tools.

Does this make my code non-actual? I don't think so. (Even though it
could obviously never compete with software written by a skilled, hired
dev team.)


> >> That should come as no surprise: it requires a lower level
> >> reasoning than doing a crossword puzzle from the newspaper.
> >
> > Ignoring for a moment that this is a factually incorrect deliberate
> > offense, isn't it the general understanding that reasoning and code
> > and development processes that require less mental strain are easier
> > to keep bug-free?
>
> I didn't say anything about less work.  A lower /level/ of reasoning
> doesn't translate to less work.
>
> How can it ever be less straining to add more code, compared to not
> adding it at all?
>
> Any monkey can read a couple of ISO standards a few times over again
> and learn to spot nonportability in code.

I strongly disagree. Most "monkeys" can't be bothered to read *any*
documentation at all. Even if they read tutorials and references, and
even if they have no difficulty implementing all kinds of algorithms
with procedural/imperative language constructs and a bit of dynamic
dispatch, they mostly hit rock bottom when they face "undefined
behavior" and "why doesn't it work on Solaris, it worked on Linux".

Obsessing about standards is tedious, boring and busywork, not noble or
creative in the least, but with my incentive in mind, it's of paramount
importance. (And it still requires more concentration than a "crossword
puzzle" -- I can tell, I do both.)


> ``Hey look, that text stream was closed and a few lines before it,
> it's clear that the last character written wasn't a newline! I'm so
> smart!''

Mock as much as you like, this is not done for circle-jerking purposes.

Have a nice day,
lacos
0
Reply lacos (176) 2/18/2010 10:25:21 AM

In article <RdWdqVoL56mp@ludens>, lacos@ludens.elte.hu (Ersek, Laszlo) writes:
> In article <20100217094624.22@gmail.com>,
> Kaz Kylheku <kkylheku@gmail.com> writes:

>> >> That should come as no surprise: it requires a lower level
>> >> reasoning than doing a crossword puzzle from the newspaper.

> Obsessing about standards is tedious, boring and busywork, not noble or
> creative in the least, but with my incentive in mind, it's of paramount
> importance. (And it still requires more concentration than a "crossword
> puzzle" -- I can tell, I do both.)


Hmm, if you meant "solving a crossword puzzle is pattern matching, and
verifying standards conformance is equally pattern matching", then I
retract the earlier "deliberate offense" bit; I misunderstood what you
meant, sorry.

Cheers,
lacos
0
Reply lacos (176) 2/18/2010 10:35:47 AM

Willem <willem@snail.stack.nl> wrote:

> Suppose that program was one in a hundred programs that were written
> without regard for free()ing every resource.  Then, afterward you had
> to go back and fix everything, which took ten times as long as it
> would have for the original programmers.  For that one program.  In
> total, it would have taken the original programmers ten times as long
> as it took now for all those programs combined.

Wrong.  If freeing resources properly is part of your natural
programming behaviour, it takes little time in most cases.  However, not
doing that causes a maintainance hell, in which such bugs need to be
found first, before they can be fixed.  You find, fix, text, find, fix,
text, etc. until the program shows the correct behaviour.  And even if
it does, there is no guarantee that you haven't overlooked something.

Clearly doing it properly in the first place is the better choice.  Bug
fixing always takes much longer than writing correct code.


> And, of course, there may have been more pragmatic solutions
> available, such as the extra layer of memory management mentioned
> elsethread, or some kind of loop that fork()s, runs the process in the
> child fork, and wait()s in the parent fork for the child to finish
> before starting the next iteration.

That's neither pragmatic, nor a solution.  Pragmatic would be
determining the scope of a resource and freeing it after that scope is
left.  The solution is to find and fix the bugs.  What you're proposing
here is just a workaround for bad program behaviour.  Also it leads to
even worse maintainance hells, because now you need to manage processes
as an additional resource.


Greets
Ertugrul


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/18/2010 12:41:12 PM

Ertugrul S=C3=B6ylemez <es@ertes.de> wrote:

> [...]  You find, fix, text, find, fix, text, etc. [...]

'test', not 'text'.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/18/2010 12:52:09 PM

On Thu, 18 Feb 2010 00:32:22 -0800 (PST), Nick Keighley
<nick_keighley_nospam@hotmail.com> wrote:

>On 17 Feb, 18:46, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
>
><snip>
>
>> What the hell is wrong with freeing resources? =A0It takes twenty seconds
>> to write the code to do it. =A0The code itself uses at most one or two
>> seconds to execute and guarantees correctness.
>
>it only "guarantees correctness" because you defined correctness as
>"freeing all resources at the end of a program".
>
>> We all know how well most commercial programs work. =A0If that is your
>> "enconomically relevant, balanced" portability, then commercial
>> application development is in a bad state.
>>
>> Serious programmers won't even argue about this topic. =A0
>
>so you, me, Seebs and Kaz aren't serious programmers?

From your mouth to the world's ears.


Richard Harter, cri@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
Infinity is one of those things that keep philosophers busy when they 
could be more profitably spending their time weeding their garden.
0
Reply cri (1432) 2/18/2010 2:43:45 PM

Seebs <usenet-nospam@seebs.net> wrote:

> On 2010-02-16, Ertugrul S=C3=B6ylemez <es@ertes.de> wrote:
> > It is a bug, but some people tolerate it, some don't.  What the
> > operating system does here is not called resource management, but
> > fault tolerance.  It should be designed not to fail on programming
> > errors.
>
> But it's not necessarily a programming error to let the operating
> system deallocate resources.  It'd be a programming error if that were
> contrary to the documented behavior of the OS.  Otherwise, it may well
> be intentional and well-considered.

I think, if it's intentional and well-considered, the compiler should
optimize it away.  The compiler is a much safer layer for such
optimizations.  If the call to 'free' is placed before a 'return' in the
main function and the main function is not called recursively, just
ignore the call (if it's safe to ignore on the target platform).

I don't know to what extent compilers like GCC implement such
optimizations.  Probably to none at all.  The problem should be fixed at
the right place.  Writing correct code should never be a problem.


> > If a program launches several worker threads and then daemonizes,
> > the operating system generally loses track of the relations.
>
> On unix-like stuff, as long as they are actually *threads*, it usually
> doesn't.

Well, sure, but you still have to kill the threads.  The operating
system is not fault tolerant here.


> >> It turns out, though, that marking the few megabytes a process used
> >> to have as "no longer in use" is much, much, cheaper than having
> >> the process try to walk through a ton of complicated data
> >> structures.
>
> > In times, where you measure processor cycles in GHz and available
> > memory in GiB and where the complexity of applications gets huge,
> > it's very dangerous to go with program exiting (!) performance.  In
> > general you will prefer correctness and predictability over a
> > slightly faster process exit.
>
> I'm not convinced.  There are a lot of programs which are, by design,
> run EXTREMELY often.

Of course, but you don't expect those programs to allocate millions of
blocks anyway.  If they do, they can't run that often anyway. =3D)


> > Remember we're not talking about in-program performance here.  We
> > are talking about program shutdown.  Also even walking a data
> > structure with millions of branches takes less than a second on
> > today's machines.
>
> I do a lot of work on a build system.  In the course of a single run
> of the build system, there are programs that get run upwards of a
> hundred thousand times.  (Say, the shell.)  In that case, I think it
> makes a great deal of sense to think very carefully about performance
> of startup and exit.

That's a good point.  I agree that there can be places, where it's
appropriate not to free memory, but that shouldn't be decided by
application programmers, but by compiler programmers.  Then it would use
the semantics of the operating system without having to write wrong
code.


> Which is why it's useful to know what the operating system's designed
> semantics are.  One could easily imagine an operating system where a
> particular device could only accept full-block writes of, say, 512
> bytes.  However, we don't then say that it is a "programming error" to
> ever write to any device except in 512-byte blocks...

That's not the same thing.  Not freeing memory doesn't change the
program's behaviour semantically.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/19/2010 7:17:21 AM

On 2010-02-19, Ertugrul Söylemez <es@ertes.de> wrote:
> The problem should be fixed at the right place.  

Yes, and that place is that big comfy chair in your psychiatrist's
office.
0
Reply kkylheku (2499) 2/19/2010 4:08:12 PM

In article <20100219080508.445@gmail.com>, Kaz Kylheku <kkylheku@gmail.com> writes:
> On 2010-02-19, Ertugrul Söylemez <es@ertes.de> wrote:
>> The problem should be fixed at the right place.  
> 
> Yes, and that place is that big comfy chair in your psychiatrist's
> office.

You know, I've been here for a short time only, and also I usually don't
like to taint my name by posting expletives, but who cares.

Fuck you, Kaz. Shove your reputation and track record up your ass. Being
right (if at all) is no excuse for being an asshole *this much*. I would
trade colleagues or co-discussants with top 1% skillset AND arrogance
for colleagues or co-discussants with top 10% skillset AND arrogance any
time.

lacos
0
Reply lacos (176) 2/19/2010 7:48:55 PM

Seebs <usenet-nospam@seebs.net> writes:

> On 2010-02-17, ImpalerCore <jadill33@gmail.com> wrote:
>
>> Why should I spend hours writing and testing manually
>> freeing resources at the end of any application, when I can get the
>> above benefits of letting the OS handle it?  (Again, I'm not referring
>> to avoiding freeing resources at all within the normal run of a
>> program, just at the end of the application.)
>
> Consistency.  If I free things when I'm done with them regardless of
> whether I'm done with them for this loop or for this program, my code
> will be more consistent and easier to follow.

Although it can be pretty painful to do so.  Consider a tree of
structures that holds an interpreted language, with tokenised
instructions, cached versions of expressions, links to lines for
conditional statements etc.  And then the data structures that get
created to hold the variables when it runs.  You've got a lot of
tree-walking to do at program termination for no good effect.
-- 
Online waterways route planner            | http://canalplan.eu
Plan trips, see photos, check facilities  | http://canalplan.org.uk
0
Reply 3-nospam (285) 2/19/2010 8:11:15 PM

"Nick" <3-nospam@temporary-address.org.uk> wrote in message 
news:87wry97zq4.fsf@temporary-address.org.uk...
> Seebs <usenet-nospam@seebs.net> writes:
>
>> On 2010-02-17, ImpalerCore <jadill33@gmail.com> wrote:
>>
>>> Why should I spend hours writing and testing manually
>>> freeing resources at the end of any application, when I can get the
>>> above benefits of letting the OS handle it?  (Again, I'm not referring
>>> to avoiding freeing resources at all within the normal run of a
>>> program, just at the end of the application.)
>>
>> Consistency.  If I free things when I'm done with them regardless of
>> whether I'm done with them for this loop or for this program, my code
>> will be more consistent and easier to follow.
>
> Although it can be pretty painful to do so.  Consider a tree of
> structures that holds an interpreted language, with tokenised
> instructions, cached versions of expressions, links to lines for
> conditional statements etc.  And then the data structures that get
> created to hold the variables when it runs.  You've got a lot of
> tree-walking to do at program termination for no good effect.

I tend to try and setup a region allocator for a given linked 
data-structure. When I want to destroy the nodes within said structure, I 
just flush the region allocator. No need to walk the tree. When this 
approach is applicable, it works like a charm. 

0
Reply no6 (2791) 2/19/2010 8:17:39 PM

On Feb 18, 11:17=A0pm, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
> nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)

That is unspeakably lame.
0
Reply chexmofo (23) 2/19/2010 8:22:33 PM

"Chris M. Thomasson" <no@spam.invalid> writes:

G> "Nick" <3-nospam@temporary-address.org.uk> wrote in message
> news:87wry97zq4.fsf@temporary-address.org.uk...
>> Seebs <usenet-nospam@seebs.net> writes:
>>
>>> On 2010-02-17, ImpalerCore <jadill33@gmail.com> wrote:
>>>
>>>> Why should I spend hours writing and testing manually
>>>> freeing resources at the end of any application, when I can get the
>>>> above benefits of letting the OS handle it?  (Again, I'm not referring
>>>> to avoiding freeing resources at all within the normal run of a
>>>> program, just at the end of the application.)
>>>
>>> Consistency.  If I free things when I'm done with them regardless of
>>> whether I'm done with them for this loop or for this program, my code
>>> will be more consistent and easier to follow.
>>
>> Although it can be pretty painful to do so.  Consider a tree of
>> structures that holds an interpreted language, with tokenised
>> instructions, cached versions of expressions, links to lines for
>> conditional statements etc.  And then the data structures that get
>> created to hold the variables when it runs.  You've got a lot of
>> tree-walking to do at program termination for no good effect.
>
> I tend to try and setup a region allocator for a given linked
> data-structure. When I want to destroy the nodes within said
> structure, I just flush the region allocator. No need to walk the
> tree. When this approach is applicable, it works like a charm. 

But unless you want to destroy the tree and carry on, this doesn't give
you much (anything?) that letting the OS do the same wouldn't give you.
A program that executes a script is likely to be in this class.
-- 
Online waterways route planner            | http://canalplan.eu
Plan trips, see photos, check facilities  | http://canalplan.org.uk
0
Reply 3-nospam (285) 2/19/2010 8:26:35 PM

On 2010-02-19, Ersek, Laszlo <lacos@ludens.elte.hu> wrote:
> Fuck you, Kaz. Shove your reputation and track record up your ass. Being
> right (if at all) is no excuse for being an asshole *this much*. I would
> trade colleagues or co-discussants with top 1% skillset AND arrogance
> for colleagues or co-discussants with top 10% skillset AND arrogance any
> time.

I'm not sure I'd phrase it that strongly, but I recently read a book
titled "The No Asshole Rule", which argued persuasively that rudeness
and hostility are not, in fact, justified by skill or expertise.  I've
been thinking about that a bit, and trying to apply it more consistently
in my own Usenet activities; I'm trying to just not respond to people
if I couldn't respond courteously.

.... Note that I do not claim to have succeeded, merely that I'm making an
effort in that direction.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/19/2010 8:33:51 PM

On 2010-02-19, Nick <3-nospam@temporary-address.org.uk> wrote:
> Seebs <usenet-nospam@seebs.net> writes:
>> Consistency.  If I free things when I'm done with them regardless of
>> whether I'm done with them for this loop or for this program, my code
>> will be more consistent and easier to follow.

> Although it can be pretty painful to do so.  Consider a tree of
> structures that holds an interpreted language, with tokenised
> instructions, cached versions of expressions, links to lines for
> conditional statements etc.  And then the data structures that get
> created to hold the variables when it runs.  You've got a lot of
> tree-walking to do at program termination for no good effect.

Ahh, not quite so!

See, the hard part isn't actually calling the tree-walker.  It's writing
it.  But I should do that in any event, because I might, say, have to parse
more than one chunk of code in the language.  So, having parsed a hunk of
code, I should definitely have a way to free the whole parsed chunk of code.

And once I've got that, it's a one-line change to free the program after
executing it.  And if that turns out to be too expensive, it's a one line
change not to do it.

Writing the code to correctly handle freeing the parse trees is valuable
and helps me ensure that my design is correct and robust.  Omitting a single
call to it strikes me as a possibly reasonable design decision to make later
based on evaluation of the cost of the tree walking, and so on -- but I've
derived the logical benefits by writing the tree walker, which I may well
end up using even though I don't free the whole parse tree at the end of
execution.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/19/2010 8:36:15 PM

"Nick" <3-nospam@temporary-address.org.uk> wrote in message 
news:87ocjl7z0k.fsf@temporary-address.org.uk...
> "Chris M. Thomasson" <no@spam.invalid> writes:
[...]
>> I tend to try and setup a region allocator for a given linked
>> data-structure. When I want to destroy the nodes within said
>> structure, I just flush the region allocator. No need to walk the
>> tree. When this approach is applicable, it works like a charm.
>
> But unless you want to destroy the tree and carry on, this doesn't give
> you much (anything?) that letting the OS do the same wouldn't give you.
> A program that executes a script is likely to be in this class.

Contrived example alert! Okay, let's say that you have an object which 
contains a linked data-structure:
_____________________________________________________________
struct tree
{
    struct tree* left;
    struct tree* right;
};


struct element
{
    struct tree node;
    /* [payload] */
};


struct object
{
    struct tree* tree;
};
_____________________________________________________________




Now, a lot of these objects get created, and start to mutate there trees. 
When it's time to destroy an object I don't want to have to manually iterate 
and destroy every damn element. I would much rather flush a region allocator 
that I setup for it. So, I would probably try to see if the following scheme 
would work for this problem:
_____________________________________________________________
struct tree
{
    struct tree* left;
    struct tree* right;
};


struct element
{
    struct tree node;
    /* [payload] */
};


struct object
{
    struct tree* tree;
    region_partition* part;
};


struct object*
object_create(region_allocator* ralloc)
{
    region_partition* part = ralloc_partiton_create(EXPANDABLE);

    if (part)
    {
        struct object* obj =
            ralloc_partiton_alloc(part, sizeof(*obj));

        if (obj)
        {
            /* initialize `obj' */

            obj->part = part;

            return obj;
        }

        ralloc_partiton_destroy(part);
    }

    return NULL;
}


struct element*
object_add(struct object* const self,
           /* [payload] */)
{
    struct element* elem =
        ralloc_partiton_alloc(self->part, sizeof(*obj));

    if (elem)
    {
        /* setup `elem' payload */

        tree_insert(&self->tree, &elem->node, /* [payload] */);
    }

    return elem;
}


void
object_destroy(struct object* const self)
{
    ralloc_partiton_destroy(self->part);
}
_____________________________________________________________



The `object_destroy()' is extremely simple. I don't have to manually iterate 
the tree just to destroy individual element objects. Instead, I destroy the 
partition that they were all allocated from. I guess you can say it's kind 
of a hybrid between automatic and manual memory management. This of course 
has many caveats, however when it's applicable to a problem, well, it works 
great!

:^) 

0
Reply no6 (2791) 2/19/2010 8:46:08 PM

Kaz Kylheku <kkylheku@gmail.com> wrote:

> On 2010-02-19, Ertugrul S=C3=B6ylemez <es@ertes.de> wrote:
> > The problem should be fixed at the right place.
>
> Yes, and that place is that big comfy chair in your psychiatrist's
> office.

Is that your reasoning?  Let me give you a hint:  It's quite poor.

Now go play elsewhere, kiddy.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/19/2010 8:46:35 PM

Oliver Jackson <chexmofo@hotmail.com> wrote:

> On Feb 18, 11:17=C2=A0pm, Ertugrul S=C3=B6ylemez <e...@ertes.de> wrote:
> > nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
>
> That is unspeakably lame.

Not everything you don't understand is lame. =3D)


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/19/2010 8:47:26 PM

In article <slrnhnttm9.574.usenet-nospam@guild.seebs.net>, Seebs <usenet-nospam@seebs.net> writes:

> I recently read a book
> titled "The No Asshole Rule", which argued persuasively that rudeness
> and hostility are not, in fact, justified by skill or expertise.

Yep, I read about it on your blog. I had a feeling in the back of my
head that somewhere I read something relevant, in a bit more articulate
form. Now I remember.

Thanks,
lacos
0
Reply lacos (176) 2/19/2010 9:30:56 PM

On Feb 19, 12:47=A0pm, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
> Oliver Jackson <chexm...@hotmail.com> wrote:
> > On Feb 18, 11:17=A0pm, Ertugrul S=F6ylemez <e...@ertes.de> wrote:
> > > nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
>
> > That is unspeakably lame.
>
> Not everything you don't understand is lame. =3D)

Feel free to explain the non-lame part I must be missing.
0
Reply chexmofo (23) 2/19/2010 10:45:00 PM

On 2010-02-19, Ersek, Laszlo <lacos@ludens.elte.hu> wrote:
> In article <20100219080508.445@gmail.com>, Kaz Kylheku <kkylheku@gmail.com> writes:
>> On 2010-02-19, Ertugrul SĂśylemez <es@ertes.de> wrote:
>>> The problem should be fixed at the right place.  
>> 
>> Yes, and that place is that big comfy chair in your psychiatrist's
>> office.
>
> You know, I've been here for a short time only, and also I usually don't
> like to taint my name by posting expletives, but who cares.
>
> Fuck you, Kaz. Shove your reputation and track record up your ass. Being
> right (if at all) is no excuse for being an asshole *this much*. I would
> trade colleagues or co-discussants with top 1% skillset AND arrogance
> for colleagues or co-discussants with top 10% skillset AND arrogance any
> time.

Hi Lacos,

We are all technically right in this debate, since we know what is going on in
the code.  This is not right versus wrong, but sane versus insane.

I honestly do not believe that someone who compares operating system process
cleanup to a mother who is taking on the room-cleaning responsibilities in
place of a ``bad'' child has an entirely firm grasp on reality.

I believe that my remark above is a perfectly crafted work of Usenet art;
the culmination of years of newsgroup experience. I wouldn't change
a word of it. (In my first draft, I used ``shrink'', but I opted to
avoid the colloquialism).

You might want to examine the reasons why you reacted to it, it clearly has
found a collateral target in you also.

I don't quite follow the numerics of your reasoning about who you would rather
work with, but you should think carefully about who the real problem
personalities are.  There are a hundred ways of being damaging that don't
involve overtly hostile, or abrupt behavior.

The root of the problem here is that we are discussing inanimate objects, which
serve us according to our requirements; to that extent they are ``good'' or
``bad''. Unlike a mother, the operating system is not an independent /person/
who suffers from taking on additional responsibilities for the sake of others. 
The very language does not fit.
0
Reply kkylheku (2499) 2/19/2010 10:50:26 PM

On Feb 19, 3:33=A0pm, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-02-19, Ersek, Laszlo <la...@ludens.elte.hu> wrote:
>
> > Fuck you, Kaz. Shove your reputation and track record up your ass. Bein=
g
> > right (if at all) is no excuse for being an asshole *this much*. I woul=
d
> > trade colleagues or co-discussants with top 1% skillset AND arrogance
> > for colleagues or co-discussants with top 10% skillset AND arrogance an=
y
> > time.
>
> I'm not sure I'd phrase it that strongly, but I recently read a book
> titled "The No Asshole Rule", which argued persuasively that rudeness
> and hostility are not, in fact, justified by skill or expertise. =A0I've
> been thinking about that a bit, and trying to apply it more consistently
> in my own Usenet activities; I'm trying to just not respond to people
> if I couldn't respond courteously.
>
> ... Note that I do not claim to have succeeded, merely that I'm making an
> effort in that direction.

I think most often its a conflict in personality types, and don't
recognize it as such.

Choleric - Like to use strong language and conflict to resolve
problems.  The details are not important to him/her.  Willing to fight
for their viewpoint.
Meloncholy - Like to find every little nit-picky problem.  Very
meticulous.  They can be depressing cause they are complainers and
hard to satisfy.
Phlegmatic - Strong desire to avoid conflict.  Tend to take a long
time to make a decision.  Tend to sit in the back and avoid being
involved.  They are quiet and suddenly blow-up to release steam.
Sanguine - Haven't personally known a software guy with this
personality yet.

The all-out flame wars are typically when 2 cholerics clash head to
head.  As a phleg myself, if someone chewed me out on the forums, I
would instinctually avoid responding to the person.

Best regards,
John D.

> -s
> --
> Copyright 2010, all wrongs reversed. =A0Peter Seebach / usenet-nos...@see=
bs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny picturesht=
tp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

0
Reply jadill33 (201) 2/19/2010 11:03:19 PM

On 2010-02-19, Kaz Kylheku <kkylheku@gmail.com> wrote:
> On 2010-02-19, Ersek, Laszlo <lacos@ludens.elte.hu> wrote:
>> In article <20100219080508.445@gmail.com>, Kaz Kylheku <kkylheku@gmail.com> writes:
>>> On 2010-02-19, Ertugrul S??ylemez <es@ertes.de> wrote:
>>>> The problem should be fixed at the right place.  

>>> Yes, and that place is that big comfy chair in your psychiatrist's
>>> office.

>> You know, I've been here for a short time only, and also I usually don't
>> like to taint my name by posting expletives, but who cares.

> I believe that my remark above is a perfectly crafted work of Usenet art;
> the culmination of years of newsgroup experience. I wouldn't change
> a word of it. (In my first draft, I used ``shrink'', but I opted to
> avoid the colloquialism).

I don't think I agree.  Insulting the previous poster is not likely to
yield positive results.  While it is quite possible that reasoned
argumentation won't either, the simplest course would be to omit the insult
entirely, since it doesn't really advance discussion.

I happen to agree more with you than with the person you flamed, but I don't
feel that the flame really improved the tone of the group.

I used to flame people a lot more.  I stopped, and I have found that I get
better results now.

-s
-- 
Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 2/19/2010 11:34:55 PM

In article <20100219140628.661@gmail.com>, Kaz Kylheku <kkylheku@gmail.com> writes:
> On 2010-02-19, Ersek, Laszlo <lacos@ludens.elte.hu> wrote:
>> In article <20100219080508.445@gmail.com>, Kaz Kylheku <kkylheku@gmail.com> writes:
>>> On 2010-02-19, Ertugrul SĂśylemez <es@ertes.de> wrote:
>>>> The problem should be fixed at the right place.  
>>> 
>>> [snip mockery]
>>
>> [snip cursing]
> 
> I believe that my remark above is a perfectly crafted work of Usenet art;
> the culmination of years of newsgroup experience.

There's no doubt about that. It's poignant and witty, indeed. A pure
essence of vileness.


> You might want to examine the reasons why you reacted to it, it clearly has
> found a collateral target in you also.

Yes, and I was expecting you to make this remark as well. (I'm saying
this in a neutral voice.)

I'm not used to being called an idiot, however indirectly. I'm convinced
you called me just that in your earlier post, to which I tried to
respond with arguments. You ignored those (perhaps because you found
them weak). I happen to share Ertugrul's view in this matter (or so I
perceive), hence I was a bit predisposed to become a target. I kind of
felt that technical opinion, and consequently, myself, attacked by this
outrageous (and certainly, witty) comment.


> I don't quite follow the numerics of your reasoning about who you would rather
> work with,

A bit less smart, but a bit more humane. Strictly in the "still smart
enough" zone.


> The root of the problem here is that we are discussing inanimate objects, which
> serve us according to our requirements; to that extent they are ``good'' or
> ``bad''. Unlike a mother, the operating system is not an independent /person/
> who suffers from taking on additional responsibilities for the sake of others. 
> The very language does not fit.

Truth to be told, I didn't read this mother-child antecedent (there's no
way to keep up with such a stream of posts), but even a very bad analogy
doesn't deserve such a comment. Or whatever, I guess I need to grow a
thicker skin. I still think you may have been seduced a little by your
own craft in creating punchlines (cf. "narcissism") -- not that I don't
like to luxuriate in my own (imaginary) smartness :)

Oh well, let's go on with the technical stuff. Sorry for the bad words,
too.

So no, I don't think we should clean up after ourselves because the OS
cannot be trusted to do that. (I don't want to use such an OS.) I simply
feel my mental hygiene ("pedantism") disturbed when I don't clean up on
a *succes* exit. (For the librarization of an application, stuff should
be cleaned up even on error exit paths, and I sometimes do that too if
the app is not multi-threaded.) I admit such hair-splitting may have
disadvantageous performance characteristics and may involve some risk,
and if it became unfeasible in any specific case, I'd probably surrender
it with conditional compilation. (I can't write a malloc() without
thinking about a free(), but I could surround the latter with an
#ifdef.) I think when we're on our way towards exit(EXIT_SUCCESS),
that's an incidental circumstance wrt. releasing allocated objects whose
usefulness has ceased due to more localized / specific grounds. (I'm
sure this doesn't make any sense.)

Perhaps plugging the leaks of an inherited monster business app written
in C is only possible in the way you suggest (patching a gc under the
app), but I still believe that choosing the other approach for new apps
shouldn't preclude them being treated as "actual software".

Sorry for repeating myself.

Cheers,
lacos
0
Reply lacos (176) 2/20/2010 1:04:24 AM

lacos@ludens.elte.hu (Ersek, Laszlo) wrote:

> I'm not used to being called an idiot, however indirectly. I'm
> convinced you called me just that in your earlier post, to which I
> tried to respond with arguments. You ignored those (perhaps because
> you found them weak). I happen to share Ertugrul's view in this matter
> (or so I perceive), hence I was a bit predisposed to become a
> target. I kind of felt that technical opinion, and consequently,
> myself, attacked by this outrageous (and certainly, witty) comment.

Really, I don't expect anyone to agree with me.  After all, my coding
style works very well for me.  I write safe code, which seldomly fails
and also sustains large scale restructuring.  That's all I care about.

These days it doesn't happen too often that I write my code in C anyway.
IMO C is retarded in every way, but unfortunately a lot of C programmers
suffer from the Blub paradox.


> So no, I don't think we should clean up after ourselves because the OS
> cannot be trusted to do that. (I don't want to use such an OS.) I
> simply feel my mental hygiene ("pedantism") disturbed when I don't
> clean up on a *succes* exit. (For the librarization of an application,
> stuff should be cleaned up even on error exit paths, and I sometimes
> do that too if the app is not multi-threaded.) I admit such
> hair-splitting may have disadvantageous performance characteristics
> and may involve some risk, and if it became unfeasible in any specific
> case, I'd probably surrender it with conditional compilation. (I can't
> write a malloc() without thinking about a free(), but I could surround
> the latter with an #ifdef.) I think when we're on our way towards
> exit(EXIT_SUCCESS), that's an incidental circumstance wrt. releasing
> allocated objects whose usefulness has ceased due to more localized /
> specific grounds. (I'm sure this doesn't make any sense.)

I'd rather listen to Linus Torvalds than to Kaz Smartass Kylheku.  Linus
even advocates the use of goto for proper cleanup before exit, be it on
success or error.  It's not that I agree to Linus in all respects, but
at least he knows the value of safe, correct code.


Greets
Ertugrul


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/20/2010 2:10:32 AM

Oliver Jackson <chexmofo@hotmail.com> wrote:

> On Feb 19, 12:47=C2=A0pm, Ertugrul S=C3=B6ylemez <e...@ertes.de> wrote:
> > Oliver Jackson <chexm...@hotmail.com> wrote:
> > > On Feb 18, 11:17=C2=A0pm, Ertugrul S=C3=B6ylemez <e...@ertes.de> wrot=
e:
> > > > nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
> > >
> > > That is unspeakably lame.
> >
> > Not everything you don't understand is lame. =3D)
>
> Feel free to explain the non-lame part I must be missing.

Feel free to pay me for giving Haskell lessons.


Greets
Ertugrul


--=20
nightmare =3D unsafePerformIO (getWrongWife >>=3D sex)
http://blog.ertes.de/

0
Reply es1 (159) 2/20/2010 2:12:06 AM

Hyman Rosen wrote:
> On 2/17/2010 9:27 AM, ImpalerCore wrote:
>  > What I meant is what is the threshold that made you decide to rely on
>  > the OS to clean up (how long was your "forever")?  1, 5, 10, 60 second
>  > shutdown?
> 
> So long that it was noticeable and annoying.
> It doesn't matter exactly how long that was.

I was running today into exact same problem. Lots of <std::string> in 
<std::map> allocated (part of our parser), and then freeing them all 
took quite a lot. Granted MSVCR90D.DLL (debug VS2008) was the culprit, 
but we needed the debug code to act fast too (part of testing), but even 
in release it takes some time (though not that much).

The way the OS frees the memory, reminds of how erlang treats it's 
processes - if process dies, the whole memory it allocated bonkers.

I also rememmber that Turbo Pascal used to have regions (kind of like 
Objective-C autorelease memory pools). Come to think of them - these are 
quite good tools, if you don't have gc.

Great postings, eye opener (I did knew about OS would free your memory, 
just never thought, although experienced, that this would slow you down).

As things that might be affected - image a Makefile calling gcc, or 
IncrediBuild calling msvc cl.exe compiler over and over - wouldn't it 
better if gcc/msvc do not free any memory? Especially if you have 64-bit 
machine, with more than 2/3 or 4GB of virtual memory, that might be better.

Or CGI, or some kind of converter (jpg -> dds, collada -> 3d model, .wav 
-> mp3) and these are scheduled with Make, IncrediBuild, Electric Cloud 
or whatever else.

In fact, one can go in these apps, and replace malloc with:

int block_pos = 0;
char block[HUGE];
void* malloc(int size)
{
   void* p = block + block_pos;
   block_pos += size;
   return p;
}

In fact this is what lots of modern video games do, yes - we try to 
avoid allocation where possible (and where not, it's usually isolated in 
a pool - say scripting system, or trie table, hash-table, etc.)

0
Reply malkia1 (193) 2/20/2010 2:33:55 AM

ImpalerCore wrote:

> I don't have a problem with the general idea of letting the OS reclaim
> memory, but I don't have the experience to know how and when to make
> the decision.  If it takes 1, 5, or 30 seconds to end the program,
> should that be a sign to just throw the hands up in the air to give it
> to the OS to handle?  Is there some other process really needing that
> extra 5 seconds?  Are users complaining about 5 seconds to close the
> program?  Is it that it costs more to develop the code to free
> everything as efficiently, so it's cheaper to just let the OS handle

What if it's a CGI script, or Makefile calling something to build?
0
Reply malkia1 (193) 2/20/2010 2:43:20 AM

Ben Bacarisse wrote:
> ImpalerCore <jadill33@gmail.com> writes:
> 
>> On Feb 16, 6:49 pm, Seebs <usenet-nos...@seebs.net> wrote:
>>> On 2010-02-16, ImpalerCore <jadil...@gmail.com> wrote:
>>>
>>>> Do you differentiate between detecting memory that is considered a
>>>> leak versus memory that you allow the OS to cleanup?
>>> I certainly do.
>>>
>>>> I would think it
>>>> would be a benefit to know if the application *can* shutdown cleanly
>>>> so that memory leaks could be determined.  Whether you consider that
>>>> time-wasting is up to you.  Does that attitude also extend to library
>>>> development?
>>> It depends a lot on circumstances.  Generally, at the least, I'd expect to
>>> know which pieces of storage I'm allocating that I expect to still be there
>>> at the end of execution.
>> Then why did I get counted off for forgetting to free memory in my
>> data structures class in college?  I wish I knew this argument back
>> then :)
> 
> OK, smiley noted, but that is not a comparable situation.  Freeing up
> the memory used by a data structure is a proper part of its
> implementation and testing that such clean-up functions work is a
> proper part of the exercise.
> 
> In practise, I'd write the memory freeing code (unless, for some
> reason, it really was very complex to write) and simply exclude the
> free-ing up code (#ifdef TIDY_UP) prior to exit if I found it was
> taking too long.
> 
> PS, yes I've used an OS that does not free memory on program exit:
> TRIPOS (and yes, there was a good reason for the OS to be designed
> that way).

I believe Symbian is like that, also WinCE if you allocate Heap's (but 
not sure). Also old Win 3.0 - 3.1 with GlobalAlloc() (I think so).
0
Reply malkia1 (193) 2/20/2010 2:45:10 AM

Ertugrul Söylemez wrote:
> Hyman Rosen <hyrosen@mail.com> wrote:
> 
>> On 2/14/2010 6:22 PM, Ertugrul Söylemez wrote:
>>> pjb@informatimago.com (Pascal J. Bourguignon) wrote:
>>>> Perhaps today, for short lived C processes, you just don't have to
>>>> care about free anymore.  Just malloc, and exit.
>>> This reasoning is used by many PHP programmers today.  It's one
>>> reason why PHP programs are so error-prone and why PHP errors are
>>> often hard to find.  There is no excuse for unfreed resources,
>>> particularly in languages, which are unsafe by nature, like C and
>>> PHP.  It _will_ get you into trouble sooner or later.
>> There is generally no need to free resources just before program exit,
>> because the operating system will do that for you - a program which
>> spends a bunch of time freeing every allocated object and then exits
>> has just wasted all of that time. It's important to free resources
>> which can be allocated in an unbounded fashion. That is, a program
>> should act like a garbage collector - unreachable objects must be
>> reclaimed, but reachable ones don't need to be.
> 
> Okay, first let's talk about C.  In C memory allocation and freeing is
> not quite fast, so you're indeed making a good point.  There is also no
> garbage collector, which does that job for you.  However, there is still
> a very important reason to free your memory.  At some point in time you
> may want to restructure your program, perhaps to enhance it, at which
> point it will get you into trouble.  We're talking about safety and
> modularity here.

On my system it's pretty fast, but I redeclare malloc/free:

int block_pos = 0;
char block[HUGE];

void* malloc(int size)
{
   void* p = block + block_pos;
   block_pos += size;
   return p;
}

void free( void *)
{
}



0
Reply malkia1 (193) 2/20/2010 3:09:52 AM

Ertugrul Söylemez wrote:
> Seebs <usenet-nospam@seebs.net> wrote:
> 
>> On 2010-02-16, Ertugrul Söylemez <es@ertes.de> wrote:
>>> So still there is no excuse for not freeing memory.
>> Again, there are a couple.  However, they're usually system-specific.
>> I can point you at an obvious case, although it's not portable:  If
>> you wish to execute another program in a UNIX-like environment, you
>> almost certainly need to allocate the space for its argument
>> list... And then your program exits to exec the other program.  You
>> must not free the memory before calling exec(), and after exec(), you
>> don't exist.
> 
> Of course, but as you say that's system-specific and you're left with no
> choice anyway.  But if you have a choice, you should choose correctness
> over small performance gains.

Why? It's like finding an umbrella, after it finished raining.
0
Reply malkia1 (193) 2/20/2010 3:12:47 AM

Nick Keighley wrote:
> On 16 Feb, 23:35, Seebs <usenet-nos...@seebs.net> wrote:
>> On 2010-02-16, Ertugrul S�ylemez <e...@ertes.de> wrote:
> 
>>> That's also the reason I suggest freeing all of the allocated memory
>>> before exiting.  If you don't, there is a closing tag missing in your
>>> program pattern.  When you restructure your program, you might
>>> accidentally forget that missing closing tag and introduce memory leaks.
>>> You know how difficult it can be to find memory leaks, if you ever
>>> notice them at all.
> 
> if you don't notice them they don't matter!
> 
>> I actually have a memory debugger I wrote to find them.  As you might expect,
>> it couldn't solve the actual problem.
> 
> I too have spent many a happy hour hunting memory leaks.
> 
>> Because, technically, it wasn't a leak -- when I went through freeing
>> everything at the end of program execution, all the allocated space got
>> freed.  However.  During execution, it was possible for a particular object
>> to end up with a linked list of unbounded size of allocated things that it
>> maintained as internal state, which were neither used nor exposed to any
>> other interface, making it very hard to find them -- and since it did free
>> them correctly on exit, there was no memory leak.
> 
> mine actually were leaks. The memory concerned no longer had any
> references to it and wouldn't be freed on shutdown.
> 
> Every time a timer was started a tiny little bit of memory went
> missing... Over a period of weeks this begins to matter!

Which means you did not shutdown/restarted your application. If that's 
the case - then you have to free the memory, but there are lots of 
applications that live for relatively small time, and are scheduled with 
build tools (Makefile, or others) - for them freeing the memory, closing 
the files is not needed.

If at some point, you decide to make these tools part of a DLL, .so, and 
instead of calling them, contain them, then you have to free them, or 
alternatively - provide them with memory block to allocate, still don't 
free, and once they are finished free the memory block (Autorelease 
pools in Objective-C, or Mark/Release() blocks in old Pascal, for "C" I 
would wrap Doug Lea's mspace and give it to them).

We do this with video games - a new level starts - there is some kind of 
stupid memory manager (usually fixed-pool allocator), and when the level 
finishes, we just kill the whole thing.
0
Reply malkia1 (193) 2/20/2010 3:17:17 AM

Ertugrul S�ylemez wrote:

> That's neither pragmatic, nor a solution.  Pragmatic would be
> determining the scope of a resource and freeing it after that scope is
> left.  The solution is to find and fix the bugs.  What you're proposing
> here is just a workaround for bad program behaviour.  Also it leads to
> even worse maintainance hells, because now you need to manage processes
> as an additional resource.

Are you sure? So none of the garbage-collecting languages are pragmatic 
for that matter?

And nothing is truer than "The solution is to find and fix the bugs", 
although there is not one program running right now without a bug (Yes, 
Knuth is an exception), all of them have.




0
Reply malkia1 (193) 2/20/2010 3:25:23 AM

Andrew Poelstra wrote:
> On 2010-02-15, Willem <willem@snail.stack.nl> wrote:
>> Richard Heathfield wrote:
>> ) santosh wrote:
>> )> Are you sure that's physical memory?
>> )
>> ) Well, of course your asking the question makes me doubt the answer, and 
>> ) I lack the time to check in more detail right now, BUT...
>> )
>> ) > During normal use (similar to
>> )> what you describe), Firefox does grab over 500 megabytes of virtual
>> )> memory, but usually only about a couple of hundred Mb of physical
>> )> memory.
>> )
>> ) *ONLY* a couple of hundred megabytes? Can you hear yourself? :-)
>>
>> <snip>
>>
>> Isn't that just the in-memory cache though ?
>> Could very well even be a config option.
>>
> 
> That might explain why it also takes ten seconds to load, while
> Opera takes four and Chrome just over one.
> 
> IME since 2.1 (IIRC) Firefox has been progressively slower and
> bloatier. The latest version was a slight uptick, but not much.
> 
>> SaSW, Willem
> 

No. That does not explain it. What it explains is, that each one of 
these browsers is just a totally different application one from each 
other - each took different strategies, or it just happened that along 
the way.

Newer windows OS comes with dynamic page swap, so it won't matter how 
much virtual memory it uses (come to think of it, it does, but 500mb is 
okay). Ten years ago, that number would've been say 15mb, 15 - 1.5mb, 
sure in 5 years this might aswell be 5gb without a problem.

The important thing is to scale with the time. I don't really care for 
executable that's only 100kb and uses another 100kb, if that executable 
is my browser.
0
Reply malkia1 (193) 2/20/2010 3:29:38 AM

Robert Latest wrote:
> ["Followup-To:" header set to comp.lang.c.]
> jacob navia wrote:
> 
>> lcc-win proposes a garbage collector in its standard distribution.
>> All the problems above are solved with a gc
> 
> Why insist on "lcc-win" when the garbage collector can be linked into
> any C program on any hosted implementation?
> 
> robert

It probably can, as long as you don't do tricks. I've never succeeded 
putting one with my apps, as I did lots of pointer fixups in loading raw 
data, or unions with casting to different types.


0
Reply malkia1 (193) 2/20/2010 3:31:27 AM

On Feb 15, 1:19=A0pm, Andrew Poelstra <apoels...@localhost.localdomain>
wrote:
> On 2010-02-15, Willem <wil...@snail.stack.nl> wrote:
>
>
>
>
>
> > Richard Heathfield wrote:
> > ) santosh wrote:
> > )> Are you sure that's physical memory?
> > )
> > ) Well, of course your asking the question makes me doubt the answer, a=
nd
> > ) I lack the time to check in more detail right now, BUT...
> > )
> > ) > During normal use (similar to
> > )> what you describe), Firefox does grab over 500 megabytes of virtual
> > )> memory, but usually only about a couple of hundred Mb of physical
> > )> memory.
> > )
> > ) *ONLY* a couple of hundred megabytes? Can you hear yourself? :-)
>
> ><snip>
>
> > Isn't that just the in-memory cache though ?
> > Could very well even be a config option.
>
> That might explain why it also takes ten seconds to load, while
> Opera takes four and Chrome just over one.
>
> IME since 2.1 (IIRC) Firefox has been progressively slower and
> bloatier.

My experience chimes with yours and Richard's. While a long-time fan,
I have recently and reluctantly had to abandon Firefox on at least
three platforms (typically in favour of Opera) as a result.

Memory and CPU bloat seem rather important problems for Firefox to
address. I have no doubt that they have the brainpower to do so, but
is it on their radar yet?

> The latest version was a slight uptick, but not much.
>
>
>
>
>
> > SaSW, Willem

0
Reply toby23 (1080) 2/20/2010 5:00:42 AM

Ersek, Laszlo wrote:

<snip>

> So no, I don't think we should clean up after ourselves because the OS
> cannot be trusted to do that. (I don't want to use such an OS.) I simply
> feel my mental hygiene ("pedantism") disturbed when I don't clean up on
> a *succes* exit.

And before Kaz sets off on another silly rant about psychiatry, it 
sounds to me like Laszlo is reaching for the word "elegance". Kaz may or 
may not appreciate the concept, but it is a genuine and valid concept 
nonetheless. For a program to leave its "housekeeping" to the OS is 
inelegant.

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 2/20/2010 7:37:04 AM

Kaz Kylheku wrote:
> On 2010-02-19, Ersek, Laszlo <lacos@ludens.elte.hu> wrote:
>> In article <20100219080508.445@gmail.com>, Kaz Kylheku <kkylheku@gmail.com> writes:
>>> On 2010-02-19, Ertugrul SĂśylemez <es@ertes.de> wrote:
>>>> The problem should be fixed at the right place.  
>>> Yes, and that place is that big comfy chair in your psychiatrist's
>>> office.
>> You know, I've been here for a short time only, and also I usually don't
>> like to taint my name by posting expletives, but who cares.
>>
>> Fuck you, Kaz. Shove your reputation and track record up your ass. Being
>> right (if at all) is no excuse for being an asshole *this much*. I would
>> trade colleagues or co-discussants with top 1% skillset AND arrogance
>> for colleagues or co-discussants with top 10% skillset AND arrogance any
>> time.
> 
> Hi Lacos,
> 
> We are all technically right in this debate, since we know what is going on in
> the code.  This is not right versus wrong, but sane versus insane.
> 
> I honestly do not believe that someone who compares operating system process
> cleanup to a mother who is taking on the room-cleaning responsibilities in
> place of a ``bad'' child has an entirely firm grasp on reality.
> 
> I believe that my remark above is a perfectly crafted work of Usenet art;
> the culmination of years of newsgroup experience. I wouldn't change
> a word of it.

Would that you had changed a dozen. It's a cheap shot, and not a 
terribly good one either. It introduced emotive language into a 
technical exchange that was getting along just fine without it.

Just as "one who disagrees with Jacob Navia" is not synonymous with 
"liar", so "one who disagrees with Kaz Kylheku" is not synonymous with 
"insane". Deal with it.

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 2/20/2010 7:55:52 AM

"Dimiter \"malkia\" Stanev" <malkia@mac.com> writes:

> ImpalerCore wrote:
>
>> I don't have a problem with the general idea of letting the OS reclaim
>> memory, but I don't have the experience to know how and when to make
>> the decision.  If it takes 1, 5, or 30 seconds to end the program,
>> should that be a sign to just throw the hands up in the air to give it
>> to the OS to handle?  Is there some other process really needing that
>> extra 5 seconds?  Are users complaining about 5 seconds to close the
>> program?  Is it that it costs more to develop the code to free
>> everything as efficiently, so it's cheaper to just let the OS handle
>
> What if it's a CGI script, or Makefile calling something to build?

A CGI program sounds a perfect example to me, although earlier in the
thread someone was claiming that PHP did this and a direct consequence
of this was the security holes PHP introduces (I paraphrase, but don't
think incorrectly).

Consider a CGI program that generates a small graphic on the fly, and a
web page contains a few dozen of them.
-- 
Online waterways route planner            | http://canalplan.eu
Plan trips, see photos, check facilities  | http://canalplan.org.uk
0
Reply 3-nospam (285) 2/20/2010 8:26:07 AM

Ertugrul S�ylemez wrote:
> Oliver Jackson <chexmofo@hotmail.com> wrote:
> 
>> On Feb 19, 12:47 pm, Ertugrul S�ylemez <e...@ertes.de> wrote:
>>> Oliver Jackson <chexm...@hotmail.com> wrote:
>>>> On Feb 18, 11:17 pm, Ertugrul S�ylemez <e...@ertes.de> wrote:
>>>>> nightmare = unsafePerformIO (getWrongWife >>= sex)
>>>> That is unspeakably lame.
>>> Not everything you don't understand is lame. =)
>> Feel free to explain the non-lame part I must be missing.
> 
> Feel free to pay me for giving Haskell lessons.
> 
> 
> Greets
> Ertugrul
> 
> 
makeWords' :: [String] -> Ptr CString -> IO ()
makeWords' [] p = do poke p nullPtr
makeWords' (s:strs) p = do poke p $ unsafePerformIO $ newCString s
                            makeWords' strs (plusPtr p $ sizeOf p)
;))))

Greets
0
Reply bmaxa209 (243) 2/20/2010 8:57:55 AM

Dimiter "malkia" Stanev wrote:
>