Backtrace function

C

CBFalconer

Richard said:
CBFalconer said:

Consider the following code:

x = y();

Is that standard C? If not, why not?

IMO Not. Because the function y is not detailed. If accompanied
by:

int y(void) {return 123;}

it becomes valid standard C.
 
K

Kaz Kylheku

Why?

It means calling

fp = GetFramePointer();

And that is standard C.

I didn't say it couldn't be done with a nonportable program, just that
it couldn't be done with a nonportable standard C program.

A program that calls a function that isn't in standard C, and which
isn't defined in that program, isn't standard C.

It can get through many of the translation phases, but at the point
when it is about to be linked together and executed, there is a
problem. Either the function doesn't exist (unresolved reference), or
it the name resolves to some nonstandard function, which may have any
behavior whatsoever.
 
K

Kaz Kylheku

CBFalconer said:

Consider the following code:

  x = y();

Is that standard C? If not, why not?

Not, because you can't have expression statements at file scope, only
declarations.

Next question?
 
F

Flash Gordon

jacob navia wrote, On 28/03/08 23:16:
Mr "Gordon":
I said this several lines below. Please read the whole message
before replying.

You said above that in non-portable C you can do it, this is not always
true.
I have the feeling that you do not red the message and try to
understand what I propose but that you jump into each sentence
trying to find out something to comment negatively on.

No, I read the entire message, and then I pointed out why your statement
that it can be done in non-portable C is not necessarily true.
The function address is always saved, or, sometimes held in a
designated register. In both cases it is at a fixed point.

On the TMS320C25 the return address could be in one of two places
depending on whether it is a leaf function or not. If it is a leaf
function the return address will have been left on the HW stack, if not
it will have been popped off the HW stack and pushed on to a stack
structure implemented in SW. How are you going to determine which is the
case? Oh, and library functions might break this rule, and certainly
functions written in assembler can.

So no, it is NOT always held in a fixed point in *real* implementations.
Obviously, if your function is *inlined* it will NOT appear
in a backtrace of the stack!

But that is "by design" isn't it?

:)

It is still a failure to show the C call stack.
See the prerequisites that I wrote below...

Had you said, "It can be done in non-portable C provided that the
following requirements are met" I might not have commented. However, you
started with an incorrect statement that it can be done in non-portable
C (which is not always true).
If there is no debug information, a backtrace can still be
printed, but it is a backrace like:

0x4477ADD()
0x4477665()

etc

The address can be still useful if you have a linker map.

So why not make your statement suitable conditional?
No. As I explained to Mr Heathfield, that raised the same objection,
my algorithm just stops at the first possible recursive call of main
It doesn't fail at all. It will not follow recursive calls to "main".

That is all.

Which means it is not correctly reporting the call stack, since the call
stack *includes* the recursive call to main.
Obviously, calling "main" recurisvely is very popular here.

:)

Actually, recursive calls to main are an abominations. However they are
allowed.
You see?

If you would have read till here, you would have saved yourself
the remarks above.

So do you accept that it is not always possible despite your claim above?
Mr "Gordon"
Writing a debugger is more complex than what I outlined above.

True.

And so what?

So what indeed? We were not talking about writing a debugger.
The purpose of my algorithm description is not to provide you
with a ready made debugger implementation!

Good, since that was not the requirement.
Specially

"Read all debug information" is quite complex as an undertaking,
I can tell you.

You don't need that for the requirement. However, the requirement is not
generally possible.

Another time your suggestion breaks is if you are in a signal handler
and the signal handlers use a separate stack, which can be the case on
*nix implementations.
 
F

Flash Gordon

jacob navia wrote, On 28/03/08 23:32:
Assuming you can get a backtrace at all, which is not guaranteed.
In principle you are right, and I considered that. Problem is, my
startup is obviously not written in C but in assembler... It would
have been quite impossible to write it in C actually...

With a few extensions you can. At least, I've worked on Pascal
implementations where the startup code was written in Pascal (+
extensions) and this is the same problem.
In my context, My assembler doesn't know how to emit debug information,
so there is no debug info.

Then perhaps you should change your assembler so that it does include
the basics. Most assemblers do.
For startups written in C, your idea would work.

Or for ones written in assembler where the assembler supports debugging.
 
R

Richard Heathfield

CBFalconer said:
IMO Not. Because the function y is not detailed.

Please cite the section of the Standard that requires the source code of a
called function to be present at compilation.

If accompanied by:

int y(void) {return 123;}

it becomes valid standard C.

So if it were accompanied by int y(void) { return 124; } that would *not*
be standard C? What are the criteria?
 
R

Richard Heathfield

Kaz Kylheku said:
Not, because you can't have expression statements at file scope, only
declarations.

Next question?

int main(void)
{
int x;

x = y();

return x;
}

:)
 
P

Philip Potter

Richard said:
jacob navia said:


Ha! Yes, we're right on the border here. Clearly, the *call* is standard.
The implementation of GetFramePointer() is not, *but* the claim was that
there was no way to do this non-portably in standard C. Standard C
implementations can legally offer extensions, and non-portable programs
can take advantage of them whilst remaining syntactically
standard-conforming. I think you win this round. Nice one.

<snip>
I think I may save this message-id for future reference :)

Phil
 
P

Philip Potter

Richard said:
Kaz Kylheku said:


int main(void)
{
int x;

x = y();

return x;
}

:)

Isn't this a constraint violation (in C99 at least)? The identifier y is
undeclared, and is therefore the expression y is not of function pointer
type.

I suggest:

int y(void);

int main(void)
{
int x;
x = y();
return x;
}
 
C

CBFalconer

Richard said:
CBFalconer said:

Please cite the section of the Standard that requires the source
code of a called function to be present at compilation.

Without that, at some point, the linking step will not function,
and you don't get an executable.
So if it were accompanied by int y(void) { return 124; } that
would *not* be standard C? What are the criteria?

Existence of valid code for the routine. You are being silly.
 
R

Richard Heathfield

CBFalconer said:
Without that, at some point, the linking step will not function,
and you don't get an executable.

You have failed to cite the section of the Standard that requires the
source code of a called function to be present at compilation. Am I to
assume that you can't find the section? Neither can I.

Addressing your non sequitur, however, consider the following code:

#include <stdio.h>

int main(void)
{
printf("Hello, world.\n");
return 0;
}

I have used implementations that don't ship their libraries in source form,
and yet the call to printf works just fine, and I *do* get an executable
program. So your non sequitur appears to be incorrect.
Existence of valid code for the routine.

So if the valid code exists, that's okay? Good. Nobody said it had to be
written in C. The standard library doesn't have to be written in C.
Implementation extensions (which are legal, according to the Standard)
don't have to be written in C.
You are being silly.

I've noticed that you often say something like this when you don't really
understand what I'm getting at. In this case, my point is simple enough -
*at compilation*, it is not necessary for a function's C source to be
visible (or even to exist) for the call to that function to be compiled
correctly. And at link time, it is only necessary for the object code to
be present in the appropriate form for linking. The Standard imposes no
requirement for the object code to have been generated from C code.

Clearly, a function that is specific to a particular implementation is
non-portable (at least in object code form) - but the point of this
discussion is not whether the program is portable but whether it is
standard. The following program is standard, non-portable C:

#include <stdio.h>
#include <myplatform.h>

int main(void)
{
printf("%d\n", mynonportablefunction());
return 0;
}

whether or not the source code of mynonportablefunction() is available.
That does not, of course, make mynonportablefunction() topical here, but
neither is the program a priori non-standard.
 
K

Kaz Kylheku

Kaz Kylheku said:








int main(void)
{
  int x;

  x = y();

  return x;

}

This isn't a complete program, but a translation unit containing an
unresolved external reference. By itself it may or may not pass the
last translation phase.

The implementation could provide a function called y() as an
extension. (For instance, pretend that ``y'' is ``read'' on POSIX). So
the linkage succeeds, and the program can be executed.

Or there could be a diagnostic about an unresolved y.

Termination with a diagnostic, or arbitrary run-time behavior. Hmm!
 
K

Kaz Kylheku

Kaz Kylheku said:




int main(void)
{
  int x;

  x = y();

Call to undeclared function. From here, I assume C89.
  return x;

}

This isn't a complete program, but a translation unit containing an
unresolved external reference. By itself it may or may not pass the
last translation phase.

The implementation could provide a function called y() as an
extension. (For instance, pretend that ``y'' is ``read'' on POSIX). So
in that case the linkage succeeds, and the program can be executed.
But we don't know what y does, or even if it returns int and can be
called with no parameters.

Or there could be a diagnostic about an unresolved y, preventing
successful linkage and execution.

Termination with a diagnostic, or arbitrary run-time behavior. Hmm!
 
P

Philip Potter

Richard said:
the point of this
discussion is not whether the program is portable but whether it is
standard. The following program is standard, non-portable C:

#include <stdio.h>
#include <myplatform.h>

int main(void)
{
printf("%d\n", mynonportablefunction());
return 0;
}

whether or not the source code of mynonportablefunction() is available.
That does not, of course, make mynonportablefunction() topical here, but
neither is the program a priori non-standard.

I'm inclined to agree intuitively with you that this program is Standard
C. What I can't then work out is where the line between Standard C and
nonstandard C is drawn. For example, the above program exhibits
undefined behaviour (not requiring a diagnostic). The following program
also does:

int main(void)
{
int i=0;
i = i++; /* yes, our favourite topic again */
return 0;
}

but I would not describe it as Standard C. Where, then, do you propose
the line be drawn?

The closest I think I can come is "If it could conceivably be one
translation unit from a set of translation units, which when taken
together form one strictly conforming C program, then it is Standard C"

This definition allows your program but rejects mine, because there
there exists a translation unit (ie one which defines
mynonportablefunction()) which will make your code strictly conforming.

Philip
 
R

Richard Heathfield

Philip Potter said:
I'm inclined to agree intuitively with you that this program is Standard
C. What I can't then work out is where the line between Standard C and
nonstandard C is drawn.

Ay, there's the rub! I think the answer depends on the context in which the
discussion is taking place.

For example, the above program exhibits
undefined behaviour (not requiring a diagnostic).

Right up until we provide a definition for mynonportablefunction(), yes.

The following program also does:

int main(void)
{
int i=0;
i = i++; /* yes, our favourite topic again */
return 0;
}

but I would not describe it as Standard C. Where, then, do you propose
the line be drawn?

I don't think a line /can/ be drawn, insofar as it really depends on what
we're trying to achieve by drawing it.
The closest I think I can come is "If it could conceivably be one
translation unit from a set of translation units, which when taken
together form one strictly conforming C program, then it is Standard C"

....even if it's non-portable standard C. Yes.
This definition allows your program but rejects mine, because there
there exists a translation unit (ie one which defines
mynonportablefunction()) which will make your code strictly conforming.

There *could* exist a translation unit, yes.
 
P

Philip Potter

Richard said:
Philip Potter said:

Ay, there's the rub! I think the answer depends on the context in which the
discussion is taking place.

Hmm, "Standard C" is sounding rather like "clc-conforming".
I don't think a line /can/ be drawn, insofar as it really depends on what
we're trying to achieve by drawing it.

I guess the purpose of drawing it in this case is to determine whether
or not a Standard C program can access the stack frame through some
nonstandard function.
...even if it's non-portable standard C. Yes.

Unfortunately I don't like this definition anymore, since I think that
code which assumes 32-bit ints is non-portable Standard C, but fails the
above test. I think I'll give up there.
 
K

Keith Thompson

Richard Heathfield said:
CBFalconer said:

Please cite the section of the Standard that requires the source code of a
called function to be present at compilation.
[...]

I suggest that this question cannot be resolved. The C standard does
not provide a definitive statement on whether a given chunk of code is
"standard C" or not. It does provide definitions of several levels of
conformance ("strictly conforming", "conforming", "correct program";
see C99 section 4), but no definition of the phrase "standard C".

And since the category of "conforming program" is so broad, it could
be argued that virtually anything is "standard C".
 
C

CBFalconer

Richard said:
.... snip ...

Addressing your non sequitur, however, consider the following
code:

#include <stdio.h>

int main(void) {
printf("Hello, world.\n");
return 0;
}

I have used implementations that don't ship their libraries in
source form, and yet the call to printf works just fine, and I
*do* get an executable program. So your non sequitur appears to
be incorrect.

I don't think it makes sense to include the C std as a portion of
every article. The above is different, because it is calling on
standard functions, specified by the standard. Certainly functions
can be written in other languages, however there are penalties, and
the result is not portable. I maintain that writing portable C
requires writing code in C, not using non-standard functions unless
std C source is given, and a few other minor niggling points.
 
R

Richard Heathfield

CBFalconer said:

Certainly functions
can be written in other languages, however there are penalties, and
the result is not portable.
Right.

I maintain that writing portable C
requires writing code in C, not using non-standard functions unless
std C source is given, and a few other minor niggling points.

Right.

So you appear to agree, now, that the code is standard, non-portable C.
Well done - you now agree with Jacob *and* me. This is quite possibly a
first in the history of comp.lang.c.
 
C

CBFalconer

Richard said:
CBFalconer said:



Right.

So you appear to agree, now, that the code is standard, non-portable
C. Well done - you now agree with Jacob *and* me. This is quite
possibly a first in the history of comp.lang.c.

Is that what this is all about? A fine distinction between
'standard' and 'portable'? To me, standard C is portable.
Non-portable C is non-standard. Again, to me.
 

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

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top