Function call sequence

M

mjm

Folks,

I have the following problem: when using arrays or matrices I often
write past the index bounds. To prevent this from happening I check
the bounds and return an error message such as

Matrix: index i=... not in [....]

However this is only of limited help since all I know now is that the
subscripting operator of Matrix was applied incorrectly.

What I really would like to know is what function called this
subscripting operator so I can tell where the mistake happened.

Is there a good solution to this?
 
K

Karl Heinz Buchegger

mjm said:
Folks,

I have the following problem: when using arrays or matrices I often
write past the index bounds. To prevent this from happening I check
the bounds and return an error message such as

Matrix: index i=... not in [....]

However this is only of limited help since all I know now is that the
subscripting operator of Matrix was applied incorrectly.

What I really would like to know is what function called this
subscripting operator so I can tell where the mistake happened.

Is there a good solution to this?

No.
The best thing is dependent on your development system.
Figure out how to stop program execution and switch to
a debugger. The debugger then can be used to walk back the call
stack.
 
K

Karl Heinz Buchegger

Karl said:
Folks,

I have the following problem: when using arrays or matrices I often
write past the index bounds. To prevent this from happening I check
the bounds and return an error message such as

Matrix: index i=... not in [....]

However this is only of limited help since all I know now is that the
subscripting operator of Matrix was applied incorrectly.

What I really would like to know is what function called this
subscripting operator so I can tell where the mistake happened.

Is there a good solution to this?

No.
The best thing is dependent on your development system.
Figure out how to stop program execution and switch to
a debugger. The debugger then can be used to walk back the call
stack.

Actually there is a way, which involves use of the preprocessor.

Assuming that your access to the matrix is enclosed in a function.

int GetValue( int x, int y );

you can add additional arguments to this function:

int GetValue( int x, int y, const char* File, const char* Line )
{
if( x_or_y_are_out_of_bounds ) {
cout << "out of bounds, called from " << File << " Line: " << Line << endl;
...
}
}

Normally you would use this function as in

z = GetValue( 3, 4, __FILE__, __LINE__ );

But since this gets boring, you use the preprocessor
to create a macro which brings in the last 2 arguments.

#define GetValue(a,b) GetValue(a,b,__FILE__,__LINE__)

z = GetValue(3, 4);

This also has the advantage that you can create different versions
for the debug and release builds easily.
 
S

Sven Gohlke

Karl said:
Actually there is a way, which involves use of the preprocessor.

Assuming that your access to the matrix is enclosed in a function.

int GetValue( int x, int y );

you can add additional arguments to this function:

int GetValue( int x, int y, const char* File, const char* Line )
{
if( x_or_y_are_out_of_bounds ) {
cout << "out of bounds, called from " << File << " Line: " << Line <<
endl; ...
}
}

Normally you would use this function as in

z = GetValue( 3, 4, __FILE__, __LINE__ );

But since this gets boring, you use the preprocessor
to create a macro which brings in the last 2 arguments.

#define GetValue(a,b) GetValue(a,b,__FILE__,__LINE__)

z = GetValue(3, 4);

This also has the advantage that you can create different versions
for the debug and release builds easily.

Since __FILE__ and __LINE__ maybe provided by the preprocessor You should
use __func__ instead which is guaranteed to be a local variable (according
to C99).
 
A

Agent Mulder

MJM>all I know now is that the subscripting operator of
MJM>Matrix was applied incorrectly.

How does the subscripting operator of Matrix looks like? Or,
if that is easier, the whole of class Matrix? I need some context
to think about your question..

-X
 
K

Karl Heinz Buchegger

Sven said:
Since __FILE__ and __LINE__ maybe provided by the preprocessor You should
use __func__ instead which is guaranteed to be a local variable (according
to C99).

as you say: C99
but this is comp.lang.c++
 
M

mjm

You can download the whole class from
http://martingale.berlios.de/Martingale.html
by following the link to CVS
(don't go to download -- that's Java code).

The subscript checking is in Array.h.

I don't think the context is necessary though.
The problem is to identify from within a call to a C++ function g(...)
the function which made the call to g(...).

I don't understand the solutions offered so far.
The function g could look like

void g(const RealArray1D& x)
{
for(int i=0;i<n;i++) {/*do something with x*/}
}

The perpetrator i is local and does not show up in the
signature of g. I guess stopping execution and using the debugger
is the only solution.

For example in Java you get the call sequence
when an exception is thrown.
 
M

mjm

Karl Heinz Buchegger said:
as you say: C99
but this is comp.lang.c++

OK, I believe I get it now.
The const char* go into the subscripting operator which is then always
called as

X(i,j,__FILE__,__LINE__)

I learned something.
What happens when the strings are passed.
If the whole string is copied this could slow down things by several
orders of magnitude since subscripting typically happens in the
innermost loops.

Anyway I like it.

Many thanks.
 
K

Karl Heinz Buchegger

mjm said:
OK, I believe I get it now.
The const char* go into the subscripting operator which is then always
called as

X(i,j,__FILE__,__LINE__)

yep. The additional macro just hides this. So the programmer
doesn't need to remember to add those 2 arguments.
I learned something.
What happens when the strings are passed.
If the whole string is copied this could slow down things by several
orders of magnitude since subscripting typically happens in the
innermost loops.

Look again at the function signature. There are no strings
involved, only character pointers.
Anyway I like it.

It's a littel bit of help. But breaking to the debugger is
usually better. The reason is that knowing where this specific
call came from often isn't very usefully. The calling function
was called from somewhere else, which was called elsewhere, etc.
So a complete call stack is needed often but not provided with this
technique.
 

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,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top