memfrob and strfry ? OT

L

lawrence.jones

Antoninus Twink said:
And more generally on POSIX. Actually, like so many things, this is
really Not A Problem in real life, but the clc regulars try to make it
into a problem so that they've got something to beef about.

There are real machines that are really in use in the real world that
have function pointers that are larger than data pointers and don't fit
in a void *. There may not be very many of them, but they're not
imaginary.

-- Larry Jones

That's the problem with nature. Something's always stinging you
or oozing mucus on you. -- Calvin
 
B

Bill Cunningham

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

int main(void) {
void *t, *p, *pp;
size_t sz;

p = malloc(1);
for (sz = 2; sz < 100; sz++) {
pp = p;
if (t = realloc(p, sz)) p = t;
else {
printf("realloc failed at sz = %lu\n", (unsigned long)sz);
break;
}
printf("p was %p, is %p at sz = %lu\n",
pp, p, (unsigned long)sz);
}
return 0;
}
Whew. Lets see if I can break this down and digest it. It looks like
malloc and realloc go together.

p = malloc(1);
for (sz = 2; sz < 100; sz++) {
pp = p;
if (t = realloc(p, sz)) p = t;

p=t is outside of the parenthesis. It looks like some shorthand I am not
good enough to decipher. I will compile this and see what happens.

Code by CB Falconer.

Bill
 
H

Harald van Dijk

Getting back on topic, the rationale is wrong about the C standard. It
states:
"Note that compilers conforming to the ISO C standard are required to
generate a warning if a conversion from a void * pointer to a function
pointer is attempted as in:
fptr = (int (*)(int))dlsym(handle, "my_function");"
This is not a syntax error and violates no constraints.
[...]
If your point is that there isn't any paragraph that specifically says
that it is not permissible to convert between void* and function
pointers, then that would be correct,

Yes, that is my point.
but neither does the C89 standard
specifically make the result implementation defined. I take it then,
that you are going for a "That which is not forbidden is permissible"
interpretation ?

When the behaviour is undefined (explicitly or by omission), there is no
requirement for a diagnostic. The standard is quite explicit about this in
a note:

3.4.3p2:
"NOTE Possible undefined behavior ranges from ignoring the situation
completely with unpredictable results, to [...]"

Additionally, when the behaviour would be undefined, except the code is
never executed, then the standard isn't entirely clear whether
implementations are allowed to reject it, but a DR cleared that up:
they're not. It's DR #109, if you would like to look it up yourself as
well.

int f(void) { return 1/0; }
int main(void) {}

This is a strictly conforming program. Any implementation that rejects it,
however useful it may be, fails to conform to the C standard. I believe
the same applies to casts between object and function pointer types, as
the behaviour is simply not defined by the standard, and there is supposed
to be no difference between behaviour undefined by omission, and behaviour
that's explicitly undefined.
 
S

santosh

Bill said:
Whew. Lets see if I can break this down and digest it. It looks
like
malloc and realloc go together.

p = malloc(1);

p=t is outside of the parenthesis. It looks like some shorthand I
am not
good enough to decipher. I will compile this and see what happens.

The realloc function is called to resize memory pointed to by 'p' to the
new size specified by 'sz'. The return value of realloc is assigned
to 't' and the resultant value of the expression is evaluated to see
whether it is "true" (non-zero value) or "false" (zero). So if realloc
succeeds the expression within the parenthesis would evaluate to true
and if realloc fails it would evaluate to false. If it evaluates as
true then the statement controlled by the if is executed, which in this
case just assigns the value in 't' to 'p', i.e., copies the new pointer
value realloc has returned into 'p'. It has to be done this way because
realloc can fail in which case the original memory is left untouched.
If the return from realloc were to be assigned to 'p' before checking
for failure then we would lose access to the original memory in the
event of realloc failure (unless the value previously in 'p' has been
cached elsewhere).
 
B

Bill Cunningham

The realloc function is called to resize memory pointed to by 'p' to the
new size specified by 'sz'. The return value of realloc is assigned
to 't' and the resultant value of the expression is evaluated to see
whether it is "true" (non-zero value) or "false" (zero). So if realloc
succeeds the expression within the parenthesis would evaluate to true
and if realloc fails it would evaluate to false. If it evaluates as
true then the statement controlled by the if is executed, which in this
case just assigns the value in 't' to 'p', i.e., copies the new pointer
value realloc has returned into 'p'. It has to be done this way because
realloc can fail in which case the original memory is left untouched.
If the return from realloc were to be assigned to 'p' before checking
for failure then we would lose access to the original memory in the
event of realloc failure (unless the value previously in 'p' has been
cached elsewhere).

Can I see this code without any type of error checking? Just plain old
calls? I seem to learn the concepts better with plain old code to serve a
purpose before error checking is added.

Bill
 
S

santosh

Bill said:
Can I see this code without any type of error checking? Just plain
old
calls? I seem to learn the concepts better with plain old code to
serve a purpose before error checking is added.

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

int main(void) {
void *t, *p, **pp;
size_t sz;

p = malloc(1);
for (sz = 2; sz < 100; sz++) {
pp = p;
p = realloc(p, sz);
printf("p was %p, is %p at sz = %lu\n",
pp, p, (unsigned long)sz);
}
return 0;
}
 
K

Keith Thompson

Bill Cunningham said:
p=t is outside of the parenthesis. It looks like some shorthand I am not
good enough to decipher. I will compile this and see what happens.

It's just an if statement; the fact that the controlled statement is
on the same line as the if makes no difference to the compiler. It's
no uncommon to write a compound statement on one line if it's short
enough (though some would argue that it's poor style).

The following are all equivalent:

if (condition) statement;

if (condition)
statement;

if (condition)
{
statement;
}

Actually the latter can be different depending on what follows it, but
in isolation they all mean the same thing.

In most contexts, whitespace and line endings do not affect the
meaning of a piece of C code *as far as the compiler is concerned*
(though they can be vitally important to human readers trying to
understand it).
 
B

Bill Cunningham

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

int main(void) {
void *t, *p, **pp;
size_t sz;

p = malloc(1);
for (sz = 2; sz < 100; sz++) {
pp = p;
p = realloc(p, sz);
printf("p was %p, is %p at sz = %lu\n",
pp, p, (unsigned long)sz);
}
return 0;
}

That is much better. I guess the only thing I don't see is the pupose
for the pp=p; statement.

Bill
 
K

Keith Thompson

Bill Cunningham said:
That is much better. I guess the only thing I don't see is the pupose
for the pp=p; statement.

It saves the value of p from before the realloc call, so you can print
both the old and new values after the realloc call. This will tell
you whether realloc had to move your chunk of memory in order to
resize it.

(Strictly speaking, you're not allowed to access the previous value
after calling realloc, but in practice it's likely to work. Just
don't try to use it for anything other than debugging.)
 
B

Barry Schwarz

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

int main(void) {
  void *t, *p, **pp;
  size_t sz;

  p = malloc(1);
  for (sz = 2; sz < 100; sz++) {
    pp = p;
    p = realloc(p, sz);
    printf("p was %p, is %p at sz = %lu\n",
               pp,        p,   (unsigned long)sz);

While I understand the intent here in replying to Bill C., it should
be noted that if realloc causes the allocated area to move (p != pp),
then this code invokes undefined behavior. The standard states that
the value of a pointer (pp in this case) becomes indeterminate when
the object it points to (in this case the allocated memory) ceases to
exist. Any attempt to evaluate an indeterminate value is prohibited.
 
B

Bill Cunningham

It saves the value of p from before the realloc call, so you can print
both the old and new values after the realloc call. This will tell
you whether realloc had to move your chunk of memory in order to
resize it.

(Strictly speaking, you're not allowed to access the previous value
after calling realloc, but in practice it's likely to work. Just
don't try to use it for anything other than debugging.)
I have been looking at my tutorials especially beginning here.
http://www.eskimo.com/~scs/cclass/notes/sx11a.html

I am trying to determine exactly what these functions are needed for.
Can I read into an object code from a file to look at with fread or fget? ?
What is realloc useful for it should be used with malloc I can see.

Bill
 
K

Keith Thompson

Bill Cunningham said:
I have been looking at my tutorials especially beginning here.
http://www.eskimo.com/~scs/cclass/notes/sx11a.html

I am trying to determine exactly what these functions are needed for.
Can I read into an object code from a file to look at with fread or fget? ?
What is realloc useful for it should be used with malloc I can see.

Which functions?

malloc and realloc are for memory management. fread and fgetc
(there's no "fget" function) read input from streams (files). They're
two very different things, though they can be used together.

What is "read into an object code" supposed to mean?

malloc() allocates a chunk of memory. realloc() resizes a chunk of
memory that's already been allocated, possibly copying it to a new
location. free() deallocations a chunk of memory that was allocated
by malloc() and/or realloc().

What exactly are you trying to accomplish?
 
B

Bill Cunningham

malloc() allocates a chunk of memory. realloc() resizes a chunk of
memory that's already been allocated, possibly copying it to a new
location. free() deallocations a chunk of memory that was allocated
by malloc() and/or realloc().

So that's what they do ok.
What exactly are you trying to accomplish?

Insead of reading from ram read into ram a file of data.

Bill
 
B

Barry Schwarz

    Insead of reading from ram read into ram a file of data.

To read from a file into memory, you first must define or allocate a
buffer. It can be as small as a single char or as large as your
system will allow. A typical example would be an array of char.

Before you can read, you must open the file usign fopen. After
checking that fopen succeeded, you have several otions to actually
transfer the data. fgetc will transfer a single character. fgets
will real a line if the fileis text. fread will read a block of
data. There are others. You chose the one that suits your needs.
When you are done processing the file, you close it with fclose.
 
B

Bill Cunningham

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

int main(void) {
void *t, *p, **pp;
size_t sz;

p = malloc(1);
for (sz = 2; sz < 100; sz++) {
pp = p;
p = realloc(p, sz);
printf("p was %p, is %p at sz = %lu\n",
pp, p, (unsigned long)sz);
}
return 0;
}

I'm beginning to see what pointers are for and it's new to me at this
stage. Pointers in the past to me have just been another way to use arrays.
Can I have an example of malloc by itself? Or is it not used by itself? For
what reasons would you use malloc?

Bill
 
S

santosh

Bill said:
I'm beginning to see what pointers are for and it's new to me at
this
stage. Pointers in the past to me have just been another way to use
arrays. Can I have an example of malloc by itself?

Sure:

int *blk;

blk = malloc(ELEMENTS * sizeof *blk);
/* In serious program you must check the return value
of malloc before proceeding. I omitted it here because
you have previously expressed difficulty understanding code
with error checking included.
*/

Here we have called malloc to attempt an allocation of ELEMENTS*sizeof
*blk bytes of memory. ELEMENTS must be defined and set to an
appropriate value previously. After the function has succeeded you
have 'blk' pointing to a contiguous sequence of the amount of bytes of
memory you passed to malloc. By accessing them through 'blk' they are
treated as an array of ELEMENTS ints. You could've also assigned the
return value to another type of pointer (say double or unsigned char)
in which case the memory is treated as a sequence of objects of the
appropriate type. This is done automatically by your compiler.
Or is it not used
by itself?

It's often used by itself.
For what reasons would you use malloc?

Malloc is used when you need to allocate storage during runtime, i.e.,
you do not know how much memory you will need until after the program
is running (for example it might depend on user or other device input).
Statically allocated memory is out-of-question while VLA have other
drawbacks (they have a smaller scope and lifetime and they is no
portable way to detect or recover from a VLA allocation failure).

Also dynamically allocated memory persists for exactly as long as you
want, no more no less. Global objects persist throughout the program's
lifetime whether or not you want that while local objects are destroyed
when their scope is exited, and again there is nothing you can do about
that. Memory derived through malloc (or realloc or calloc) is available
until you deallocate it with free or until the program terminates.
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,952
Messages
2,570,111
Members
46,692
Latest member
NewtonChri

Latest Threads

Top