473,385 Members | 1,429 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Function invocation location

I was wondering if it would be possible to find out, from within a
function, the file and line number where that particular function call
was invoked, bearing in mind that the function can potentially be
invoked from many different files. I guess that what I am looking for
is something similar to the __FILE__ and __LINE__ symbols, but one
level up in the function call stack.

Dec 22 '05 #1
15 1352
1.*****@gmail.com writes:
I was wondering if it would be possible to find out, from within a
function, the file and line number where that particular function call
was invoked, bearing in mind that the function can potentially be
invoked from many different files. I guess that what I am looking for
is something similar to the __FILE__ and __LINE__ symbols, but one
level up in the function call stack.


No, there's no good portable way to do that.

You could probably do something involving passing extra arguments to
your functions, but it wouldn't be pretty.

A source level debugger should be able to show this information
interactively.

What are you trying to accomplish?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 22 '05 #2
I use macros to do it

#include <stdio.h>

#define perform_action(a) _perform_action((a),__FILE__,__LINE__)
void _perform_action(int actCd, const char * file, int lineno);
void _perform_action(int actCd, const char * file, int lineno) {
printf("Called perform_action from %s:%d\n", file, lineno);
}
int main(void) {
perform_action(4);
return 0;
}

Dec 22 '05 #3
Keith Thompson wrote:
1.*****@gmail.com writes:
I was wondering if it would be possible to find out, from within a
function, the file and line number where that particular function call
was invoked, bearing in mind that the function can potentially be
invoked from many different files. I guess that what I am looking for
is something similar to the __FILE__ and __LINE__ symbols, but one
level up in the function call stack.


No, there's no good portable way to do that.

You could probably do something involving passing extra arguments to
your functions, but it wouldn't be pretty.

A source level debugger should be able to show this information
interactively.

What are you trying to accomplish?


Pretty much what I said: To find out who is invoking a certain
function, and at what point. I am using an embedded environment, and a
source level debugger does disturb things so that what I am trying to
see is not there anymore. The only way I could think of to do it is by
means of the info above, and well-placed printf (the output of which
goes to a console accessible through a serial port).

Dec 22 '05 #4
You can also (sometimes) get stack trace information on linux with the
functions: backtrace and backtrace_symbols. I don't remember what
information you could get from the functions (if it was file, line, or
function/symbol name), but I think you could get symbol names for
functions that weren't static.

Dec 22 '05 #5
ca************@gmail.com writes:
I use macros to do it
You use macros to do what? Please read
<http://cfaj.freeshell.org/google/>. Google's posting interface is
badly broken, but it can be used correctly with just a little extra
effort.
#include <stdio.h>

#define perform_action(a) _perform_action((a),__FILE__,__LINE__)
void _perform_action(int actCd, const char * file, int lineno);
Avoid identifiers with leading underscores. Many of them are reserved
for use by the implementation. Rather than memorizing or looking up
the rules for which ones are reserved in which contexts, it's best to
just avoid them altogether (unless you're using something defined for
you by the implementation).

If you want to generate an identifier from an existing one, trailing
underscores are ok.
void _perform_action(int actCd, const char * file, int lineno) {
printf("Called perform_action from %s:%d\n", file, lineno);
}
int main(void) {
perform_action(4);
return 0;
}


Otherwise, that looks reasonable. It's a lot of extra work, it only
goes up one level (going up arbitrarily many levels is going to be
interesting), and it only works for functions for which you
specifically provide the feature.

The most likely reason you'd want this information is for debugging.
In that case, a good source-level debugger should give you that
information and a lot more as well. If you want the behavior of the
function to vary depending on where it's called from, that's almost
certainly a bad idea, better implemented by just passing an extra
argument to control the behavior.

As with a lot of low-level stuff like this, the first thing you should
do is step back and decide what problem you're actually trying to
solve. It's likely that there's a better and/or more portable
solution.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 22 '05 #6
1.*****@gmail.com writes:
Keith Thompson wrote:
1.*****@gmail.com writes:
> I was wondering if it would be possible to find out, from within a
> function, the file and line number where that particular function call
> was invoked, bearing in mind that the function can potentially be
> invoked from many different files. I guess that what I am looking for
> is something similar to the __FILE__ and __LINE__ symbols, but one
> level up in the function call stack.


No, there's no good portable way to do that.

You could probably do something involving passing extra arguments to
your functions, but it wouldn't be pretty.

A source level debugger should be able to show this information
interactively.

What are you trying to accomplish?


Pretty much what I said: To find out who is invoking a certain
function, and at what point. I am using an embedded environment, and a
source level debugger does disturb things so that what I am trying to
see is not there anymore. The only way I could think of to do it is by
means of the info above, and well-placed printf (the output of which
goes to a console accessible through a serial port).


If a source level debugger masks the problem, it's likely that either
the debugger is broken or you're dealing with undefined behavior. You
can do what you want by changing your code, but that's also likely to
disturb things. (It's worth a try, though.)

If you know how the compiler lays out stack frames, you *might* be
able to display the return address in, say, hexadecimal, and map that
back to the point at which the function was called. This is clearly
*extremely* system-specific, so we can't really go into it here, but
it might give you what you need.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 22 '05 #7
ca************@gmail.com wrote:
I use macros to do it

#include <stdio.h>

#define perform_action(a) _perform_action((a),__FILE__,__LINE__)
void _perform_action(int actCd, const char * file, int lineno);
void _perform_action(int actCd, const char * file, int lineno) {
printf("Called perform_action from %s:%d\n", file, lineno);
}
int main(void) {
perform_action(4);
return 0;
}


Would this not stop working if, instead of using the name of the
function itself, one invokes it via a pointer?

Dec 23 '05 #8
Keith Thompson a écrit :
[snip]
If a source level debugger masks the problem, it's likely that either
the debugger is broken or you're dealing with undefined behavior.
It is impossible for a debugger to mask itself completely.
Having written a debugger for embedded systems I can tell you,
the debugger is a BIG mess that comes upon your poor program.

Impossible to do otherwise in cramped conditions, no RAM,
no MMU, etc.

That the program has "undefined behavior" is obvious, if not he
would not be trying to debug !!!
You
can do what you want by changing your code, but that's also likely to
disturb things. (It's worth a try, though.)

I agree with you in this. The printfs do CHANGE things, and even if
the impact is smaller than the impact of the debugger, they DO CHANGE
the program, as you said.
If you know how the compiler lays out stack frames, you *might* be
able to display the return address in, say, hexadecimal, and map that
back to the point at which the function was called. This is clearly
*extremely* system-specific, so we can't really go into it here, but
it might give you what you need.


That is the best solution for this problem. Find out how the
compiler lays out the stack frame (an assembly listing will do that)
and try to send the hexadecimal return address through the serial
line.

With the help of a link map, you can figure out where you were called from.
jacob
Dec 23 '05 #9
Keith Thompson wrote:
1.*****@gmail.com writes:
Keith Thompson wrote:
1.*****@gmail.com writes:
> I was wondering if it would be possible to find out, from within a
> function, the file and line number where that particular function call
> was invoked, bearing in mind that the function can potentially be
> invoked from many different files. I guess that what I am looking for
> is something similar to the __FILE__ and __LINE__ symbols, but one
> level up in the function call stack.

No, there's no good portable way to do that.

You could probably do something involving passing extra arguments to
your functions, but it wouldn't be pretty.

A source level debugger should be able to show this information
interactively.

What are you trying to accomplish?
Pretty much what I said: To find out who is invoking a certain
function, and at what point. I am using an embedded environment, and a
source level debugger does disturb things so that what I am trying to
see is not there anymore. The only way I could think of to do it is by
means of the info above, and well-placed printf (the output of which
goes to a console accessible through a serial port).


If a source level debugger masks the problem, it's likely that either
the debugger is broken or you're dealing with undefined behavior. You
can do what you want by changing your code, but that's also likely to
disturb things. (It's worth a try, though.)


There are some timing considerations that the debugger interferes
with in an unavoidable way. On the other hand, a few printf statements
do not disturb such considerations significantly.

If you know how the compiler lays out stack frames, you *might* be
able to display the return address in, say, hexadecimal, and map that
back to the point at which the function was called. This is clearly
*extremely* system-specific, so we can't really go into it here, but
it might give you what you need.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.


Dec 23 '05 #10
jacob navia <ja***@jacob.remcomp.fr> writes:
Keith Thompson a écrit :
[snip]
If a source level debugger masks the problem, it's likely that either
the debugger is broken or you're dealing with undefined behavior.


It is impossible for a debugger to mask itself completely.
Having written a debugger for embedded systems I can tell you,
the debugger is a BIG mess that comes upon your poor program.

Impossible to do otherwise in cramped conditions, no RAM,
no MMU, etc.

That the program has "undefined behavior" is obvious, if not he
would not be trying to debug !!!


Not at all. All we know is that the program has incorrect behavior.
It could be the result of unspecified behavior, system-defined
behavior, or just an incorrect algorithm. The fact that using a
source level debugger changes the behavior makes it likely that the
problem is caused by undefined behavior, but it's still not certain.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 23 '05 #11
Keith Thompson wrote:

<snip>
If a source level debugger masks the problem, it's likely that either
the debugger is broken or you're dealing with undefined behavior.
The arguably broken debugger is definitely one that happens in real
life. I've dealt with a processor where the only ICE and simulator both
broke the behaviour of the processor pipeline whenever the code hit a
breakpoint or when you single stepped. I considered it to be severely
broken, but there were no alternatives available.
You
can do what you want by changing your code, but that's also likely to
disturb things. (It's worth a try, though.)
Yes, definitely worth a try.
If you know how the compiler lays out stack frames, you *might* be
able to display the return address in, say, hexadecimal, and map that
back to the point at which the function was called. This is clearly
*extremely* system-specific, so we can't really go into it here, but
it might give you what you need.


Or the compiler might have an extension to do it, but as Keith says this
is highly system specific.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Dec 23 '05 #12
jacob navia wrote:
Keith Thompson a écrit :
[snip]
If a source level debugger masks the problem, it's likely that either
the debugger is broken or you're dealing with undefined behavior.
It is impossible for a debugger to mask itself completely.


Not always the case except in terms hardware timings. Some In-Circuit
Emulators I have used, that come with high-level language debuggers, use
special versions of the chips that allow the ICE to stop the processor
dead and examine everything (including the internal registers) without
disturbing anything.
Having written a debugger for embedded systems I can tell you,
the debugger is a BIG mess that comes upon your poor program.
Not always the case.
Impossible to do otherwise in cramped conditions, no RAM,
no MMU, etc.
Not always the case, since the debugger may not even be running on the
same processor. See ICE above.
That the program has "undefined behavior" is obvious, if not he
would not be trying to debug !!!
No, it could be any kind of error, not necessarily undefined behaviour.
You
can do what you want by changing your code, but that's also likely to
disturb things. (It's worth a try, though.)


I agree with you in this. The printfs do CHANGE things, and even if
the impact is smaller than the impact of the debugger, they DO CHANGE
the program, as you said.


Indeed. Also, if it is an embedded system, sometimes a logic analyser is
the best tool.
If you know how the compiler lays out stack frames, you *might* be
able to display the return address in, say, hexadecimal, and map that
back to the point at which the function was called. This is clearly
*extremely* system-specific, so we can't really go into it here, but
it might give you what you need.


That is the best solution for this problem. Find out how the
compiler lays out the stack frame (an assembly listing will do that)
and try to send the hexadecimal return address through the serial
line.


Check the documentation before reading the assembly output. There may be
extensions to help, or the documentation may tell you what the stack
layout is.
With the help of a link map, you can figure out where you were called from.


Not always that simple if there are dynamically loaded libraries, since
they might not always be loaded to the same address.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Dec 23 '05 #13
Flash Gordon a écrit :
jacob navia wrote:
Keith Thompson a écrit :
[snip]
If a source level debugger masks the problem, it's likely that either
the debugger is broken or you're dealing with undefined behavior.

It is impossible for a debugger to mask itself completely.

Not always the case except in terms hardware timings. Some In-Circuit
Emulators I have used, that come with high-level language debuggers, use
special versions of the chips that allow the ICE to stop the processor
dead and examine everything (including the internal registers) without
disturbing anything.


Well, that's a debugger with hardware assist. We do not all have
that luxury...

The debugger I wrote was for a chip that was designed and built around
a chip that offered 80K Ram, that could not be used for debugging,
and program memory (EPROM) that could not be altered. The compiler
would emit instructions at each line to test for a line breakpoints
array.

If the current line was found in the array, it would change
to a "server" mode that sent info to the PC debugger. HELL I can
tell you!
Having written a debugger for embedded systems I can tell you,
the debugger is a BIG mess that comes upon your poor program.

Not always the case.


Of course not. Maybe in the debuggers I wrote only :-) Or the debugger
writers are much more lucky, benefit from hardware assist, etc.
Impossible to do otherwise in cramped conditions, no RAM,
no MMU, etc.

Not always the case, since the debugger may not even be running on the
same processor. See ICE above.


If your processor doesn't have any ICE or breakpoint instruction
the debugger becomes tricky even if the real debugger runs in a PC.
That the program has "undefined behavior" is obvious, if not he
would not be trying to debug !!!

No, it could be any kind of error, not necessarily undefined behaviour.


Errors that disappear when the debugger steps in are mostly UB, except
of timing constraints.
Dec 23 '05 #14
jacob navia wrote:
Flash Gordon a écrit :
jacob navia wrote:
Keith Thompson a écrit :
[snip]

If a source level debugger masks the problem, it's likely that either
the debugger is broken or you're dealing with undefined behavior.

It is impossible for a debugger to mask itself completely.


Not always the case except in terms hardware timings. Some In-Circuit
Emulators I have used, that come with high-level language debuggers,
use special versions of the chips that allow the ICE to stop the
processor dead and examine everything (including the internal
registers) without disturbing anything.


Well, that's a debugger with hardware assist. We do not all have
that luxury...


Agreed. I fully accept that sometimes debuggers have to work within the
limitations you talked about, it's just not always the case.

Anyway, this is OT here, so I think we should drop it.

<snip>
Not always the case, since the debugger may not even be running on the
same processor. See ICE above.


If your processor doesn't have any ICE or breakpoint instruction
the debugger becomes tricky even if the real debugger runs in a PC.


You can always write a complete emulation of the hardware and run the
emulation on a PC (or other powerful computer) which, of course,
potentially gives the debugger full control since the "processor" is
then part of the debugger rather than a real piece of HW :-)

I've seen it done and used such simulator debuggers, just a pittle the
ones I used were very badly written.
That the program has "undefined behavior" is obvious, if not he
would not be trying to debug !!!


No, it could be any kind of error, not necessarily undefined behaviour.


Errors that disappear when the debugger steps in are mostly UB, except
of timing constraints.


I've come across many real world situations where there was no undefined
behaviour, but there was a timing issue. Or, as in the code I debugged
the day before yesterday, if something external responds too slowly the
code invokes undefined behaviour, but if you step through the code the
external event happens fast enough so you don't invoke undefined
behaviour. I identified the bug by the use of valgrind and code inspection.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Dec 23 '05 #15

1.*****@gmail.com wrote:
ca************@gmail.com wrote:
I use macros to do it

#include <stdio.h>

#define perform_action(a) _perform_action((a),__FILE__,__LINE__)
void _perform_action(int actCd, const char * file, int lineno);
void _perform_action(int actCd, const char * file, int lineno) {
printf("Called perform_action from %s:%d\n", file, lineno);
}
int main(void) {
perform_action(4);
return 0;
}


Would this not stop working if, instead of using the name of the
function itself, one invokes it via a pointer?

You are right. Since you can't get the address of a macro you would
have to use the address of the real function, which would mean you
would have to explicitly pass __FILE__ and __LINE__.

Dec 23 '05 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Michael | last post by:
Guys, I'm interested in how the compiler implements function calls, can anyone correct my understanding/point me towards some good articles. When a function is called, is the stack pointer...
4
by: deko | last post by:
When I loop through this function, it works fine until it hits End Function - then it jumps to End Select. Very strange... This behavior occurs when Case = 255. Any ideas why this is happening? ...
7
by: Newbie_sw2003 | last post by:
Where should I use them? I am giving you my understandings. Please correct me if I am wrong: MACRO: e.g.:#define ref-name 99 The code is substituted by the MACRO ref-name. So no overhead....
4
by: Victor | last post by:
Hello, I've got a situation in which the number of (valid) recursive calls I make will cause stack overflow. I can use getrlimit (and setrlimit) to test (and set) my current stack size. ...
8
by: Ravindranath Gummadidala | last post by:
Hi All: I am trying to understand the C function call mechanism. Please bear with me as I state what I know: "every invocation of a function causes a frame for that function to be pushed on...
4
by: anonymous | last post by:
Thanks your reply. The article I read is from www.hakin9.org/en/attachments/stackoverflow_en.pdf. And you're right. I don't know it very clearly. And that's why I want to understand it; for it's...
3
by: wernerf | last post by:
Hi all. Here's my problem: Consider a package MY_PKG with the following two functions FUNCTION get_number_by_rowid( p_table_name IN VARCHAR2, ...
36
by: Julienne Walker | last post by:
Ignoring implementation details and strictly following the C99 standard in terms of semantics, is there anything fundamentally flawed with describing the use of a (non-inline) function as an...
5
by: Peter Olcott | last post by:
Does anyone know of any good software that automatically produces a function call invocation diagram for C/C++ programs? I think that this would be very useful for determining the possible...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.