purge like utility in c

  • Thread starter ramasubramanian.rahul
  • Start date
R

Richard Heathfield

jacob navia said:
What "C"?

(a) The language defined by "The C Programming Language", 1st edition
(b) The language defined by ISO/IEC 9899:1990
(c) The language defined by ISO/IEC 9899:1999

All of these languages, and no others, have a reasonable claim to be called
"C". None of them incorporates a garbage collector.
The garbage collector can be used as an external library.

Third-party libraries are not topical here.
 
R

Richard Heathfield

jacob navia said:
Interesting. You recommend valgrind,

No, I just mentioned it, that's all. I don't recommend it (and neither do I
recommend against it). How can I? I've never needed to use it. But I am
told by its users that it's very helpful to them.
but you are against a Garbage Collector.

My understanding of valgrind is that you can use it without modifying your C
source code, so the program remains uncorrupted by the tool. And, having
used it to identify and remove any leaks from your program, the program
remains portable, and can still work independently of valgrind, so
portability is not affected.

Is my understanding of valgrind incorrect? Or, if I've got it about right,
can you claim the same characteristics for your garbage collector? That is,
can it work without the C source having to call any of its routines, and
will the program still work correctly without leaking memory even when that
program is moved to a platform where the garbage collector is unavailable?
If so, then I remove my objections. Otherwise, I don't.
 
R

Richard Heathfield

jacob navia said:

Look, seeing the pain in the... of malloc/free,

Of all the things in C that can cause pain, this is one of the most trivial.
It is fairly easy not to leak memory, and remarkably easy to detect memory
leaks. If you can't do it, fine, but that's your problem, nobody else's.
 
F

Flash Gordon

jacob said:
Interesting. You recommend valgrind, but you are against a Garbage
Collector.

Does "C" has a "valgrind"????

No, I do not find that word in my copy of the C standard. But that is OK
of course. You can recommend valgrind, but when I recommend a garbage
collector the hell rains over me and I am flamed of being "a troll".

<snip>

Stop talking complete rubbish. As you well know valgrind can be used
with any standard C program where as garbage collection cannot.
 
F

Frederick Gotham

Richard Heathfield posted:
Third-party libraries are not topical here.


I suppose the most basic form would be something like:

#include <stddef.h>
#include <stdlib.h>

typedef struct AllocLink {
void *p;
struct AllocLink *p_prev;
} AllocLink;

AllocLink first_link = {0,0};
AllocLink *plink = &first_link;

void *mallocGC(size_t const len)
{
void freeGC(void);

static int first_time = 1;
AllocLink *const p_new_link = malloc(sizeof *p_new_link);

if (!p_new_link) return 0;

p_new_link->p = malloc(len);

if(!p_new_link->p) { free(p_new_link); return 0; }

p_new_link->p_prev = plink;

plink = p_new_link;

if(first_time) first_time = 0, atexit(freeGC);

return plink->p;
}

void freeGC(void)
{
AllocLink *p_prev;

do
{
free(plink->p);
p_prev = plink->p_prev;
free(plink);
plink = p_prev;
} while(plink->p);
}


The behaviour would be undefined if you were to use "free" to deallocate
memory allocated by "mallocGC".
 
S

Simon Biber

jacob said:
C was designed with a GC in mind.

How can a GC decide whether a value in memory is actually a pointer or not?

static intptr_t b;

{
char *a = malloc(1000);
b = (intptr_t)a ^ 0xDEADBEEF;
a = NULL;
some_long_procedure();
a = (char*) (b ^ 0xDEADBEEF);
do_something_with(a);
}

During the execution of some_long_procedure() there is no memory
containing the address of the allocated block. The pointer has been
safely stashed in an integer and obfuscated by XORing it. What if the GC
goes ahead and collects the memory, and it's no longer available later?

What about this:

{
char *a = malloc(1000);
FILE *fp = fopen("tmp", "wb");
fwrite(&a, sizeof a, 1, fp);
fclose(fp);
a = NULL;

some_long_procedure();

fp = fopen("tmp", "rb");
fread(&a, sizeof a, 1, fp);
fclose(fp);

do_something_with(a);
}
 
J

jacob navia

Flash said:
<snip>

Stop talking complete rubbish. As you well know valgrind can be used
with any standard C program where as garbage collection cannot.

Who is talking complete rubbish?

Here is a list of limitations of valgrind:


Valgrind will run Linux ELF binaries, on a kernel 2.4.X or 2.6.X system,
on the x86, amd64, ppc32 and ppc64 architectures, subject to the
following constraints:

*

On x86 and amd64, there is no support for 3DNow! instructions. If
the translator encounters these, Valgrind will generate a SIGILL when
the instruction is executed. Apart from that, on x86 and amd64,
essentially all instructions are supported, up to and including SSE2.
Version 3.1.0 includes limited support for SSE3 on x86. This could be
improved if necessary.

On ppc32 and ppc64, almost all integer, floating point and
Altivec instructions are supported. Specifically: integer and FP insns
that are mandatory for PowerPC, the "General-purpose optional" group
(fsqrt, fsqrts, stfiwx), the "Graphics optional" group (fre, fres,
frsqrte, frsqrtes), and the Altivec (also known as VMX) SIMD instruction
set, are supported.
*

Atomic instruction sequences are not properly supported, in the
sense that their atomicity is not preserved. This will affect any use of
synchronization via memory shared between processes. They will appear to
work, but fail sporadically.
*

If your program does its own memory management, rather than using
malloc/new/free/delete, it should still work, but Valgrind's error
checking won't be so effective. If you describe your program's memory
management scheme using "client requests" (see The Client Request
mechanism), Memcheck can do better. Nevertheless, using malloc/new and
free/delete is still the best approach.
*

Valgrind's signal simulation is not as robust as it could be.
Basic POSIX-compliant sigaction and sigprocmask functionality is
supplied, but it's conceivable that things could go badly awry if you do
weird things with signals. Workaround: don't. Programs that do non-POSIX
signal tricks are in any case inherently unportable, so should be
avoided if possible.
*

Machine instructions, and system calls, have been implemented on
demand. So it's possible, although unlikely, that a program will fall
over with a message to that effect. If this happens, please report ALL
the details printed out, so we can try and implement the missing feature.
*

Memory consumption of your program is majorly increased whilst
running under Valgrind. This is due to the large amount of
administrative information maintained behind the scenes. Another cause
is that Valgrind dynamically translates the original executable.
Translated, instrumented code is 12-18 times larger than the original so
you can easily end up with 50+ MB of translations when running (eg) a
web browser.
*

Valgrind can handle dynamically-generated code just fine. If you
regenerate code over the top of old code (ie. at the same memory
addresses), if the code is on the stack Valgrind will realise the code
has changed, and work correctly. This is necessary to handle the
trampolines GCC uses to implemented nested functions. If you regenerate
code somewhere other than the stack, you will need to use the
--smc-check=all flag, and Valgrind will run more slowly than normal.
*

As of version 3.0.0, Valgrind has the following limitations in
its implementation of x86/AMD64 floating point relative to IEEE754.

Precision: There is no support for 80 bit arithmetic. Internally,
Valgrind represents all such "long double" numbers in 64 bits, and so
there may be some differences in results. Whether or not this is
critical remains to be seen. Note, the x86/amd64 fldt/fstpt instructions
(read/write 80-bit numbers) are correctly simulated, using conversions
to/from 64 bits, so that in-memory images of 80-bit numbers look correct
if anyone wants to see.

The impression observed from many FP regression tests is that the
accuracy differences aren't significant. Generally speaking, if a
program relies on 80-bit precision, there may be difficulties porting it
to non x86/amd64 platforms which only support 64-bit FP precision. Even
on x86/amd64, the program may get different results depending on whether
it is compiled to use SSE2 instructions (64-bits only), or x87
instructions (80-bit). The net effect is to make FP programs behave as
if they had been run on a machine with 64-bit IEEE floats, for example
PowerPC. On amd64 FP arithmetic is done by default on SSE2, so amd64
looks more like PowerPC than x86 from an FP perspective, and there are
far fewer noticable accuracy differences than with x86.

Rounding: Valgrind does observe the 4 IEEE-mandated rounding
modes (to nearest, to +infinity, to -infinity, to zero) for the
following conversions: float to integer, integer to float where there is
a possibility of loss of precision, and float-to-float rounding. For all
other FP operations, only the IEEE default mode (round to nearest) is
supported.

Numeric exceptions in FP code: IEEE754 defines five types of
numeric exception that can happen: invalid operation (sqrt of negative
number, etc), division by zero, overflow, underflow, inexact (loss of
precision).

For each exception, two courses of action are defined by 754:
either (1) a user-defined exception handler may be called, or (2) a
default action is defined, which "fixes things up" and allows the
computation to proceed without throwing an exception.

Currently Valgrind only supports the default fixup actions.
Again, feedback on the importance of exception support would be appreciated.

When Valgrind detects that the program is trying to exceed any of
these limitations (setting exception handlers, rounding mode, or
precision control), it can print a message giving a traceback of where
this has happened, and continue execution. This behaviour used to be the
default, but the messages are annoying and so showing them is now
optional. Use --show-emwarns=yes to see them.

The above limitations define precisely the IEEE754 'default'
behaviour: default fixup on all exceptions, round-to-nearest operations,
and 64-bit precision.
*

As of version 3.0.0, Valgrind has the following limitations in
its implementation of x86/AMD64 SSE2 FP arithmetic, relative to IEEE754.

Essentially the same: no exceptions, and limited observance of
rounding mode. Also, SSE2 has control bits which make it treat
denormalised numbers as zero (DAZ) and a related action, flush denormals
to zero (FTZ). Both of these cause SSE2 arithmetic to be less accurate
than IEEE requires. Valgrind detects, ignores, and can warn about,
attempts to enable either mode.
*

As of version 3.2.0, Valgrind has the following limitations in
its implementation of PPC32 and PPC64 floating point arithmetic,
relative to IEEE754.

Scalar (non-Altivec): Valgrind provides a bit-exact emulation of
all floating point instructions, except for "fre" and "fres", which are
done more precisely than required by the PowerPC architecture
specification. All floating point operations observe the current
rounding mode.

However, fpscr[FPRF] is not set after each operation. That could
be done but would give measurable performance overheads, and so far no
need for it has been found.

As on x86/AMD64, IEEE754 exceptions are not supported: all
floating point exceptions are handled using the default IEEE fixup
actions. Valgrind detects, ignores, and can warn about, attempts to
unmask the 5 IEEE FP exception kinds by writing to the floating-point
status and control register (fpscr).

Vector (Altivec, VMX): essentially as with x86/AMD64 SSE/SSE2: no
exceptions, and limited observance of rounding mode. For Altivec, FP
arithmetic is done in IEEE/Java mode, which is more accurate than the
Linux default setting. "More accurate" means that denormals are handled
properly, rather than simply being flushed to zero.

Programs which are known not to work are:

emacs starts up but immediately concludes it is out of memory and
aborts. It may be that Memcheck does not provide a good enough emulation
of the mallinfo function. Emacs works fine if you build it to use the
standard malloc/free routines.
 
J

jacob navia

Richard said:
jacob navia said:




No, I just mentioned it, that's all. I don't recommend it (and neither do I
recommend against it). How can I? I've never needed to use it. But I am
told by its users that it's very helpful to them.




My understanding of valgrind is that you can use it without modifying your C
source code, so the program remains uncorrupted by the tool. And, having
used it to identify and remove any leaks from your program, the program
remains portable, and can still work independently of valgrind, so
portability is not affected.

Is my understanding of valgrind incorrect? Or, if I've got it about right,
can you claim the same characteristics for your garbage collector? That is,
can it work without the C source having to call any of its routines, and
will the program still work correctly without leaking memory even when that
program is moved to a platform where the garbage collector is unavailable?
If so, then I remove my objections. Otherwise, I don't.

You do:
#define malloc(a) GC_malloc(a)
#define free(a)

And that is it.
Most programs will work like this, unless (of course) they write
pointers to a file, or put their pointers in e-mail messages, or
whatever.

We have discussed this several times.

By the way, the limitations of valgrind are FAR more long. See my reply
to "Flash Gordon"...
 
R

Roland Pibinger

Define "most powerful". It's certainly not the most useful in many cases.

And the better idiom for resource management is?
And for many "types" pre-allocating is very much not the safest option
(like string types).

pre-allocating? It's merely about the symmetry of allocation and
deallocation (eg. malloc/free) in one scope.
It also strongly ties the caller to the callee
implicitly, which you often don't want from a design/quality POV.

The ties are explicit and the responsibilities are clear: Whoever
allocates a resource has to deallocate/release it in the same scope.
Well apart from *alloc, there are at least two in the Std. library: fopen
and tmpfile. Both due to not wanting the callee to have to know intimately
about the object created. If you then get out of the theoretical there
are many more examples like: asprintf, acl_get_file and opendir.

The point is that you allocate a resource (with malloc, fopen,
opendir, ...) which you symmetrically deallocate/release (with free,
fclose, closedir, ...).

Best regards,
Roland Pibinger
 
R

Richard Heathfield

jacob navia said:
Who is talking complete rubbish?

Here is a list of limitations of valgrind:

....none of which is relevant to the fact that valgrind is an external
utility, like gdb or time or gprof or cat or type. It isn't part of the
program. You don't render your program non-portable by using it. Unlike
your garbage collection thing.

<snip>
 
R

Richard Heathfield

jacob navia said:

You do:
#define malloc(a) GC_malloc(a)
#define free(a)

And that is it.

foo.c:117: warning: implicit declaration of function `GC_malloc'
foo.c:117: warning: initialization makes pointer from integer without a cas
foo.c:117: undefined reference to `GC_malloc'
collect2: ld returned 1 exit status
make: *** [foo] Error 1
 
J

jacob navia

Richard said:
jacob navia said:

You do:
#define malloc(a) GC_malloc(a)
#define free(a)

And that is it.


foo.c:117: warning: implicit declaration of function `GC_malloc'
foo.c:117: warning: initialization makes pointer from integer without a cas
foo.c:117: undefined reference to `GC_malloc'
collect2: ld returned 1 exit status
make: *** [foo] Error 1

Yes, do not use GC_malloc. You see?
It doesn't work.


Stay with "free" and "malloc" Heathfield. GC_malloc is too much for you.
 
J

jacob navia

Richard said:
jacob navia said:




...none of which is relevant to the fact that valgrind is an external
utility, like gdb or time or gprof or cat or type. It isn't part of the
program. You don't render your program non-portable by using it. Unlike
your garbage collection thing.

<snip>

Boehm's GC runs under linux, windows, hp unices, and *many* OS.

But I do not want that YOU use a GC Heathfield, since it is
too much for you. Stay with your malloc/free.

Besides, if you use the GC you will not be able to run in the embedded
OS in your toaster.

WHO CARES?
 
J

jacob navia

Frederick said:
Richard Heathfield posted:





I suppose the most basic form would be something like:

#include <stddef.h>
#include <stdlib.h>

typedef struct AllocLink {
void *p;
struct AllocLink *p_prev;
} AllocLink;

AllocLink first_link = {0,0};
AllocLink *plink = &first_link;

void *mallocGC(size_t const len)
{
void freeGC(void);

static int first_time = 1;
AllocLink *const p_new_link = malloc(sizeof *p_new_link);

if (!p_new_link) return 0;

p_new_link->p = malloc(len);

if(!p_new_link->p) { free(p_new_link); return 0; }

p_new_link->p_prev = plink;

plink = p_new_link;

if(first_time) first_time = 0, atexit(freeGC);

return plink->p;
}

void freeGC(void)
{
AllocLink *p_prev;

do
{
free(plink->p);
p_prev = plink->p_prev;
free(plink);
plink = p_prev;
} while(plink->p);
}


The behaviour would be undefined if you were to use "free" to deallocate
memory allocated by "mallocGC".

Maybe. Better do not use it.

Use malloc/free and do everything manually with all the associated bugs.

I was recommending the GC for other people that like caring about their
programs, their algorithms, their deadlines, instead of chasing
malloc/free bugs!!!

You like malloc/free?

OK. I do not earn any percentages in GC sales!
 
J

jacob navia

Richard said:
jacob navia said:




Of all the things in C that can cause pain, this is one of the most trivial.
It is fairly easy not to leak memory, and remarkably easy to detect memory
leaks. If you can't do it, fine, but that's your problem, nobody else's.

Incredible.

There is a whole INDUSTRY of software for chasing
malloc/free bugs. Huge software systems like valgrind,
purify, etc etc are built JUST TO CHASE THOSE BUGS.

Incredible, it is SO EASY to avoid any problems and
there are SO MANY people trying to fix that!!!

They are all stupid, like me... They did not see what
Heathfield sees... Damm it!
 
R

Richard Heathfield

jacob navia said:
Richard said:
jacob navia said:

You do:
#define malloc(a) GC_malloc(a)
#define free(a)

And that is it.


foo.c:117: warning: implicit declaration of function `GC_malloc'
foo.c:117: warning: initialization makes pointer from integer without a
cas foo.c:117: undefined reference to `GC_malloc'
collect2: ld returned 1 exit status
make: *** [foo] Error 1

Yes, do not use GC_malloc. You see?
It doesn't work.

Precisely so.
Stay with "free" and "malloc" Heathfield. GC_malloc is too much for you.

On the contrary, it's not enough.
 
R

Richard Heathfield

jacob navia said:

Boehm's GC runs under linux, windows, hp unices, and *many* OS.

That's funny. I tried it under Linux and it didn't even exist, let alone
run.

WHO CARES?

You don't, obviously. But comp.lang.c is for discussions about C, not
discussions about stuff that isn't C.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top