Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Question about C

Reply
Thread Tools

Question about C

 
 
Malcolm McLean
Guest
Posts: n/a
 
      05-09-2010
On May 9, 6:25*pm, spinoza1111 <(E-Mail Removed)> wrote:
>
> You can get both in .Net, and you can call the compiler which means
> you can change both. In principle (I haven't figured out myself how to
> do it).
>
> So much for C's "power".
>

You're kind of right. Real second generation languages (as opposed to
the jargony use of the term 4gl to refer to scripts with flashy user
interfaces) will provide mechanisms for altering and extending the
program as it runs. However we haven't figured out how to do this in a
useful way yet. I've heard that Lisp makes the attempt.

 
Reply With Quote
 
 
 
 
Nick Keighley
Guest
Posts: n/a
 
      05-09-2010
On 9 May, 16:39, Malcolm McLean <(E-Mail Removed)>
wrote:
> On May 9, 6:25*pm, spinoza1111 <(E-Mail Removed)> wrote:
>
> > You can get both in .Net, and you can call the compiler which means
> > you can change both. In principle (I haven't figured out myself how to
> > do it).

>
> > So much for C's "power".

>
> You're kind of right. Real second generation languages (as opposed to
> the jargony use of the term 4gl to refer to scripts with flashy user
> interfaces) will provide mechanisms for altering and extending the
> program as it runs. However we haven't figured out how to do this in a
> useful way yet. I've heard that Lisp makes the attempt.


well you can load and even write code at run time, make fixes to live
systems etc.
I believe Forth attempted this as well



 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      05-09-2010
jacob navia <(E-Mail Removed)> writes:

> Phil Carmody a écrit :
>> Willem <(E-Mail Removed)> writes:
>>> sandeep wrote:
>>> ) Hello jacob ~~
>>> )
>>> ) You probably know it, but that code will NOT work on a platform
>>> where C ) is interpreted not compiled.
>>>
>>> Right.
>>>
>>> ) Also a static function could be completely ) removed by the
>>> compiler since it is not externally visible, then you ) would get
>>> the first opcodes of main().
>>>
>>> Wrong.
>>> Taking the address of a function forces the compiler to keep a copy
>>> of it.


Nit: taking the address happens all the time so I think you mean storing
the address somewhere. A simple call like f() involves "taking the
address" of f (at least by some reasonable senses of the term).

>> Chapter and verse, please?
>>
>> Surely if the address is never used, then the as-if rule permits a
>> compiler to have no copy of the function. No strictly conforming
>> program could tell if the function was really there or not.

>
> The address *IS* used. It is assigned to a char pointer that is used
> for printf. THEN
>
> (1) Apparently you can't read. Get better glasses.
> (2) If the compiler removes it, it has a bug.


Can you explain why this is a bug? I've used a C compiler in which
(char *)f produces a pointer to an essentially random location unrelated
to f in any way. I can't see why a C compiler has to keep a copy of f
around unless something useful can be done with it.

--
Ben.
 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      05-09-2010
Ben Bacarisse a écrit :
>
> Nit: taking the address happens all the time so I think you mean storing
> the address somewhere. A simple call like f() involves "taking the
> address" of f (at least by some reasonable senses of the term).
>


I mean "taking the address". If you take the address without storing it anywhere like in f(), the
function MUST be kept since it is called. If you take the address to store it somewhere, it is used
too, and must be kept.

>>> Chapter and verse, please?
>>>
>>> Surely if the address is never used, then the as-if rule permits a
>>> compiler to have no copy of the function. No strictly conforming
>>> program could tell if the function was really there or not.

>> The address *IS* used. It is assigned to a char pointer that is used
>> for printf. THEN
>>
>> (1) Apparently you can't read. Get better glasses.
>> (2) If the compiler removes it, it has a bug.

>
> Can you explain why this is a bug?


See above. If I take the address of f() and store it in a function table, to be part of one of my
VTables and used in my container library, the compiler MUST keep the function code.

>I've used a C compiler in which
> (char *)f produces a pointer to an essentially random location unrelated
> to f in any way.


Great! In that machine nothing will work.

So what?

I would recommend you to keep that machine away from me.



> I can't see why a C compiler has to keep a copy of f
> around unless something useful can be done with it.


Yes, but I would prefer that compilers stay what they are: compilers.

The day a compiler decides that my program is not useful because there is nothing interesting coming
out of it and decides to erase my source files I will stop programming. There is no point in
programming such compilers anyway. You just tell them:

Write my program compiler!

And they will do it without bothering anyone with programming tasks.

Until that day arrives, I will go on programming with this simple assumptions:

(1) I am the one writing the program.
(2) The compiler COMPILES my code to machine code
(3) The circuit board executes what the compiler compiled.

Yes, I know. In your (wonderful and mysterious) machine, making

(char *)f

produces a random pointer. In that machine too, the compiler decides
that functions whose address is taken and stored can be "optimized"
away.

OK. Be it. I never used such a machine, and I would rather prefer not having to worry about them.

jacob
 
Reply With Quote
 
Tom St Denis
Guest
Posts: n/a
 
      05-09-2010
On May 9, 11:25*am, spinoza1111 <(E-Mail Removed)> wrote:
> On May 9, 5:13*pm, sandeep <(E-Mail Removed)> wrote:
>
>
>
>
>
> > jacob navia writes:
> > > #include <math.h>
> > > #include <stdio.h>

>
> > > static int fn(int s)
> > > {
> > > * * * * *if (s > 0)
> > > * * * * * * *return sqrt(s)/pow(s,3);
> > > * * * * *else return pow(s,3);
> > > }

>
> > > int main(void)
> > > {
> > > * * * * *int (*fptr)(int) = fn;
> > > * * * * *char *p = (char *)fptr;

>
> > > * * * * *printf("First 10 bytes of the opcodes of fn are:\n"); for (int
> > > * * * * *i = 0; i<10;i++) {
> > > * * * * * * * * *printf("[%d] %d 0x%x\n",i,p[i],p[i]);
> > > * * * * *}
> > > }

>
> > Hello jacob ~~

>
> > You probably know it, but that code will NOT work on a platform where C
> > is interpreted not compiled. Also a static function could be completely
> > removed by the compiler since it is not externally visible, then you
> > would get the first opcodes of main().

>
> > Regards ~~

>
> How about a version of C in which you could get and change both source
> and object code at all times?
>
> You can get both in .Net, and you can call the compiler which means
> you can change both. In principle (I haven't figured out myself how to
> do it).
>
> So much for C's "power".
>
> Hmm...taking Herb Schildt's old C interpreter...porting it
> to .Net...adding this ability...nyhah ha haaah


Dunno about you but I wouldn't want to run programs where it's
standard that users can change it's functionality (in terms of running
new code out of the control of the original developer).

As another pointed out you can always load a dynamic object if you
need to add flexibility at runtime...

Tom
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      05-09-2010
sandeep <(E-Mail Removed)> writes:
> jacob navia writes:
>> #include <math.h>
>> #include <stdio.h>
>>
>> static int fn(int s)
>> {
>> if (s > 0)
>> return sqrt(s)/pow(s,3);
>> else return pow(s,3);
>> }
>>
>> int main(void)
>> {
>> int (*fptr)(int) = fn;
>> char *p = (char *)fptr;
>>
>> printf("First 10 bytes of the opcodes of fn are:\n");
>> for (int i = 0; i<10;i++) {
>> printf("[%d] %d 0x%x\n",i,p[i],p[i]);
>> }
>> }


[The code layout was messed up in sandeep's followup; I've tried to
correct it.]

> You probably know it, but that code will NOT work on a platform where C
> is interpreted not compiled.


The code is not guaranteed to "work" on any implementation (unless
the implementation makes guarantees beyond those provided by the
standard). The behavior of a conversion from type int (*)(int) to
type char* is undefined. If you disagree, please cite the wording
in the standard that defines the behavior.

There are non-interpreted implementations on which a function
pointer does not contain the machine address of the function's code.
On some, it points to a descriptor that contains more information
about the function. On others (AS/400?), a function pointer *is*
a descriptor, and is much larger than a char*.

> Also a static function could be completely
> removed by the compiler since it is not externally visible,


Yes. If the program took the function's address and then used that
address to call the function, the implementation could not remove the
function (unless it performed some additional optimization on the call,
such as inlining it). But in this case, since the program's behavior
is undefined, the compiler can do anything it likes.

> then you
> would get the first opcodes of main().


How did you reach that conclusion? I suppose that's one possibility,
but it's more likely you'd get the bytes from the location where the
code for fn() *would* have been stored. That, or a segmentation fault.

Even if p actually points to the code for fn(), trying to use the
converted pointer to modify that code is likely to fail.

Yes, jacob's program is likely to work as intended on many systems. But
it's not likely to be particularly useful. And using unsigned char
rather than char produces better output; I got:

First 10 bytes of the opcodes of fn are:
[0] 85 0x55
[1] -119 0xffffff89
[2] -27 0xffffffe5
[3] -125 0xffffff83
[4] -20 0xffffffec
[5] 56 0x38
[6] -125 0xffffff83
[7] 125 0x7d
[8] 8 0x8
[9] 0 0x0

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <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"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      05-09-2010
jacob navia <(E-Mail Removed)> writes:
> Ben Bacarisse a écrit :
>>
>> Nit: taking the address happens all the time so I think you mean storing
>> the address somewhere. A simple call like f() involves "taking the
>> address" of f (at least by some reasonable senses of the term).
>>

>
> I mean "taking the address". If you take the address without storing
> it anywhere like in f(), the function MUST be kept since it is
> called. If you take the address to store it somewhere, it is used too,
> and must be kept.


Taking the address of a function does not call the function.

Consider:

#include <stdio.h>

static void func(void)
{
puts("This is never called");
}

int main(void)
{
void (*funcptr)(void) = func;
puts("Note that the value of funcptr is not used");
return 0;
}

The generated code for this program is not required to contain code that
prints the string "This is never called".

>>>> Chapter and verse, please?
>>>>
>>>> Surely if the address is never used, then the as-if rule permits a
>>>> compiler to have no copy of the function. No strictly conforming
>>>> program could tell if the function was really there or not.
>>> The address *IS* used. It is assigned to a char pointer that is used
>>> for printf. THEN
>>>
>>> (1) Apparently you can't read. Get better glasses.
>>> (2) If the compiler removes it, it has a bug.

>>
>> Can you explain why this is a bug?

>
> See above. If I take the address of f() and store it in a function
> table, to be part of one of my VTables and used in my container
> library, the compiler MUST keep the function code.


Correct, if the compiler is unable to prove that the address is never
used to call the function. But in both the code I wrote above, and in
the code that you previously posted, the compiler may be able to prove
that the function is never called, and therefore that its address is
never used.

Compilers are permitted to perform optimizations that do not change the
visible behavior of the program.

Note that a call isn't the only thing that can require the compiler to
keep the function's address. For example, an equality comparison to
another function's address must also work correctly. But the behavior
of a conversion to char* is undefined, so it doesn't prevent the
compiler from eliminating the function's code.

Of course the compiler isn't *required* to perform any such
optimizations; it's free to emit code for the function anyway.

>>I've used a C compiler in which
>> (char *)f produces a pointer to an essentially random location unrelated
>> to f in any way.

>
> Great! In that machine nothing will work.


I suspect that "unrelated to f in any way" was an exaggeration. It's
entirely plausible that a function pointer could point to a descriptor,
where it's the descriptor that contains the address of the function's
code and other information. Converting a function pointer to
char* might let you access the descriptor, but it wouldn't let you
(directly) access the function's code. The descriptor is certainly
related to the function, but the memory address of the descriptor
has no clear relation to the address of the function's code.

There have also been machines where code and data occupy separate
address spaces. C is carefully designed to be usable on such systems.

[...]

jacob, I understand that you're not interested in seeing factual
corrections from me, but perhaps others might benefit from this.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <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"
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      05-09-2010
jacob navia <(E-Mail Removed)> writes:

> Ben Bacarisse a écrit :
>>
>> Nit: taking the address happens all the time so I think you mean storing
>> the address somewhere. A simple call like f() involves "taking the
>> address" of f (at least by some reasonable senses of the term).
>>

>
> I mean "taking the address". If you take the address without storing
> it anywhere like in f(), the function MUST be kept since it is
> called. If you take the address to store it somewhere, it is used too,
> and must be kept.


Why? Can't it be inlined even if this is not requested?

>>>> Chapter and verse, please?
>>>>
>>>> Surely if the address is never used, then the as-if rule permits a
>>>> compiler to have no copy of the function. No strictly conforming
>>>> program could tell if the function was really there or not.
>>> The address *IS* used. It is assigned to a char pointer that is used
>>> for printf. THEN
>>>
>>> (1) Apparently you can't read. Get better glasses.
>>> (2) If the compiler removes it, it has a bug.

>>
>> Can you explain why this is a bug?

>
> See above. If I take the address of f() and store it in a function
> table, to be part of one of my VTables and used in my container
> library, the compiler MUST keep the function code.


See above. I doubt any compiler can -- or even tries to -- inline a
function call once the address has been stored, but you seem to be
saying that it would be a compiler bug if it did. If the function has
internal linkage and all calls have been inlined I don't see any
requirement from the standard that the code must there as a separate
addressable entity.

[The function could be removed even if it has external linkage if the
compiler or linker is very sophisticated, but why would anyone bother to
do that?]

>>I've used a C compiler in which
>> (char *)f produces a pointer to an essentially random location unrelated
>> to f in any way.

>
> Great! In that machine nothing will work.


Eh? It worked very well. Code injection attacks were almost impossible
but legitimate access to executable memory simply required a little help
from the OS.

> So what?
>
> I would recommend you to keep that machine away from me.
>
>


You're safe. The last time I saw one was in a museum (literally).

>> I can't see why a C compiler has to keep a copy of f
>> around unless something useful can be done with it.

>
> Yes, but I would prefer that compilers stay what they are: compilers.
>
> The day a compiler decides that my program is not useful because there
> is nothing interesting coming out of it and decides to erase my source
> files I will stop programming. There is no point in programming such
> compilers anyway. You just tell them:
>
> Write my program compiler!
>
> And they will do it without bothering anyone with programming tasks.
>
> Until that day arrives, I will go on programming with this simple assumptions:
>
> (1) I am the one writing the program.
> (2) The compiler COMPILES my code to machine code
> (3) The circuit board executes what the compiler compiled.


That's beside the point. On a machine were data accesses can't
(normally) access executable code (char *)f has no meaning. What would
you have the compiler do? C is defined in such a way that it can be
implemented on a machine like that. If you don't like that design,
don't buy that kind of hardware, but you can't say it's a bug for a
compiler to ignore C code that is meaningless on the target it is
compiling for.

> Yes, I know. In your (wonderful and mysterious) machine, making
>
> (char *)f
>
> produces a random pointer. In that machine too, the compiler decides
> that functions whose address is taken and stored can be "optimized"
> away.
>
> OK. Be it. I never used such a machine, and I would rather prefer not
> having to worry about them.


That's fine; and anyone writing (char *)f is obviously doing the same.
I have no problem with that, but the question was about what would
constitute a bug in a C compiler. That's a more general question than
what constitutes a bug in a compiler that you'd like to use of Intel
hardware.

--
Ben.
 
Reply With Quote
 
William Hughes
Guest
Posts: n/a
 
      05-10-2010
On May 9, 10:40*am, Malcolm McLean <(E-Mail Removed)>
wrote:
> On May 9, 4:17*pm, Phil Carmody <(E-Mail Removed)>
> wrote:
>
> > Willem <(E-Mail Removed)> writes:
> > > sandeep wrote:
> > > ) Hello jacob ~~
> > > )
> > > ) You probably know it, but that code will NOT work on a platform where C
> > > ) is interpreted not compiled.

>
> > > Right.

>
> > > ) Also a static function could be completely
> > > ) removed by the compiler since it is not externally visible, then you
> > > ) would get the first opcodes of main().

>
> > > Wrong.
> > > Taking the address of a function forces the compiler to keep a copy of it.

>
> > Chapter and verse, please?

>
> > Surely if the address is never used, then the as-if rule permits a
> > compiler to have no copy of the function. No strictly conforming
> > program could tell if the function was really there or not.

>
> In theory yes, it's undefined behaviour once the function pointer is
> cast to an unsigned char *, so the compiler is free to inline the
> function and report an error message when the cast is executed. In
> fact it's probably too hard and also pointless for a compiler to make
> this distinction - if a function's address is taken, it won't inline
> it, or at least will make a non-inlined copy


If the compiler first takes the "address" of the function, then
casts it to a (char *) I would agree that it is unlikely that
the implementation would take advantage of the fact that undefined
behaviour was invoked to inline the function. However, in this
case taking the address of the function and casing it to (char* )
may take place at the same time. Indeed, it is not until the cast
the the compiler knows it needs an "address" for the function.
If the complier knows that the cast will not produce a predictable
result [1] it may simply use 0 for the value of the (char *) and
*not* mark the function as having the address taken. The compiler
is then free to only inline the function.

- William Hughes

[1] The cast invokes undefined behaviour, so the compiler can
use 0 no matter what. However, the compiler will probably not
make use of this license if there is at least a
semi-reasonable meaning for the cast,

 
Reply With Quote
 
Stargazer
Guest
Posts: n/a
 
      05-10-2010
On May 9, 8:51*pm, jacob navia <(E-Mail Removed)> wrote:
> Ben Bacarisse a crit :
>
>
>
> > Nit: taking the address happens all the time so I think you mean storing
> > the address somewhere. *A simple call like f() involves "taking the
> > address" of f (at least by some reasonable senses of the term).

>
> I mean "taking the address". If you take the address without storing it anywhere like in f(), the
> function MUST be kept since it is called. If you take the address to store it somewhere, it is used
> too, and must be kept.


Actually, case for your code is especially mentioned in "portability
issues" (Annex K):

"K.5 Common extensions


[#1] The following extensions are widely used in many
systems,
but are not portable to all implementations. The inclusion
of
any extension that may cause a strictly conforming program
to
become invalid renders an implementation nonconforming."

and further:

K.5.7 Function pointer casts


[#1] A pointer to an object or to void may be cast to a
pointer
to a function, allowing data to be invoked as a function
(6.3.4).

[#2] A pointer to a function may be cast to a pointer to
an
object or to void, allowing a function to be inspected
or
modified (for example, by a debugger) (6.3.4).

In particular, your code will fail (read crash) in some common cases
if:

1) Instruction and data pointers are of different size
2) Instructions and data reside in separate segments / address spaces
3) Code section is non-readable (execute-only)

>
> >>> Chapter and verse, please?
> >>> Surely if the address is never used, then the as-if rule permits a
> >>> compiler to have no copy of the function. No strictly conforming
> >>> program could tell if the function was really there or not.
> >> The address *IS* used. It is assigned to a char pointer that is used
> >> for printf. THEN

>
> >> (1) Apparently you can't read. Get better glasses.
> >> (2) If the compiler removes it, it has a bug.

>
> > Can you explain why this is a bug? *

>
> See above. If I take the address of f() and store it in a function table, to be part of one of my
> VTables and used in my container library, the compiler MUST keep the function code.


The compiler needs not at least "keep the function code". You can
assign a pointer to external function, of which compiler knows
nothing.

BTW, you used "static" storage specifier in your example, but I
couldn't fund any precise requirements for "static" functions in the
standard (other than the "static" specifier may be used. I know what
is the "common handling" but can you (or anybody else) provide
citation for static functions?

> >I've used a C compiler in which
> > (char *)f produces a pointer to an essentially random location unrelated
> > to f in any way.

>
> Great! In that machine nothing will work.
>
> So what?
>
> I would recommend you to keep that machine away from me.
>
>


IIRC, at least on some AIX platforms when you looked at function's
pointer it pointed to relocatable unconditional branch instruction. I
don't remember all the details, but apparently it was because the
architecture didn't allow indirect branches from data section, so
relocation had to include patching the instruction.

> > I can't see why a C compiler has to keep a copy of f
> > around unless something useful can be done with it.

>
> Yes, but I would prefer that compilers stay what they are: compilers.
>
> The day a compiler decides that my program is not useful because there is nothing interesting coming
> out of it and decides to erase my source files I will stop programming. There is no point in
> programming such compilers anyway. You just tell them:
>
> Write my program compiler!
>
> And they will do it without bothering anyone with programming tasks.
>
> Until that day arrives, I will go on programming with this simple assumptions:
>
> (1) I am the one writing the program.
> (2) The compiler COMPILES my code to machine code


.... according the the language's specifications.

> (3) The circuit board executes what the compiler compiled.


If the compiler compiles not according to the C standard requirements
(or possibly with additional requirements), then it's not a C
compiler. Even if you devise your own language, once you release
specifications you'll practically have to follow them since.

Daniel
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
question row filter (more of sql query question) =?Utf-8?B?YW5kcmV3MDA3?= ASP .Net 2 10-06-2005 01:07 PM
Quick Question - Newby Question =?Utf-8?B?UnlhbiBTbWl0aA==?= ASP .Net 4 02-16-2005 11:59 AM
Question on Transcender Question :-) eddiec MCSE 6 05-20-2004 06:59 AM
Question re: features of the 831 router (also a 924 question) Wayne Cisco 0 03-02-2004 07:57 PM
Syntax Question - Novice Question sean ASP .Net 1 10-20-2003 12:18 PM



Advertisments