473,378 Members | 1,319 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,378 software developers and data experts.

Any way to do this in C?

Howdy,

Forgive me for not looking this up in the manuals or just trying
it outright, as I don't have access to a shell right now. Anyway, I
thought of this while juggling earlier: it would be neat if there were
a way to do a "sizeof" on the total set of declarations at the top of a
given function. For example:

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

int main( int argc, char **argv )
{
char a;
char b;
int x,y,z;

printf( "The 'main' function declares %d bytes of data.\n\r", sizeof(
*main ) );
return 0;
}

Why would this be useful, you ask? Think nested recursion. Often,
programmers will clumsily use a semi-magical number to limit the max
depth before a recursion will be forcefully halted with an error.
Compare the following (you'll forgive the "code fragment" nature here,
since I'm using made-up syntax in the 2nd version anyway, there's
little point being pedantic elsewhere) (and yes, I know these use more
memory than needed but I'm doing that on purpose to illustrate my
point):

int my_recursive_fnc( int n )
{
static int depth;
int x,y,z,answer;

if ( ++depth MY_MAGIC_NUMBER )
{
printf( "Fatal: recursion nest too deep\n\r" );
exit(0);
}

x = do_some_stuff( &n, &y, &z );
answer = my_recursive_fnc( n + x + y + z );
depth--;
return answer;
}

versus:

int my_recursive_fnc( int n )
{
extern int recursion_bytes;
int x,y,z,answer;

recursion_bytes += sizeof( *my_recursive_fnc );

if ( recursion_bytes sysdata.max_space_for_recursion )
{
printf( "Fatal: recursion exceeded user-defined RAM limit\n\r" );
exit(0);
}

x = do_some_stuff( &n, &y, &z );
answer = my_recursive_fnc( n + x + y + z );
recursion_bytes -= sizeof( *my_recursive_fnc );
return answer;
}

In the 2nd version, instead of a magical hardcoded nest limit, we have
a realtime user-defined RAM limit which gives more leeway to more
efficient recursive functions and can nicely track recursion memory
throughout interwoven recursive functions that call eachother. This
could be done by manually adding the sizeof's of all the declared
variables as well as the passed-in arguments, but that would be a
maintainance and readability nightmare, and might even skip over
padding.

Sep 29 '06 #1
5 1582
On 28 Sep 2006 20:21:20 -0700, "Snis Pilbor" <sn********@yahoo.com>
wrote:
>Howdy,

Forgive me for not looking this up in the manuals or just trying
it outright, as I don't have access to a shell right now. Anyway, I
thought of this while juggling earlier: it would be neat if there were
a way to do a "sizeof" on the total set of declarations at the top of a
given function. For example:
<..>

You may group all of the local variables within a single struct, and
then evaluate sizeof the struct

Zara
Sep 29 '06 #2

Zara wrote:
On 28 Sep 2006 20:21:20 -0700, "Snis Pilbor" <sn********@yahoo.com>
wrote:
Howdy,

Forgive me for not looking this up in the manuals or just trying
it outright, as I don't have access to a shell right now. Anyway, I
thought of this while juggling earlier: it would be neat if there were
a way to do a "sizeof" on the total set of declarations at the top of a
given function. For example:
<..>

You may group all of the local variables within a single struct, and
then evaluate sizeof the struct

Zara
Oh hey, you are right Zara, that's a good point. =) Thanks for
bringing it up. But I see some problems with it. The biggest one is
that it doesn't include the memory used by the passed-in arguments: if
my function is "char some_function( char x )", it's going to use at
least 1 byte even if it declares no other memory at all. Though I
guess that's still a big improvement, since one tends to change
passed-in parameters much less frequently than variable declarations,
so one could manually add their sizeof's without quite as big a
maintainance nightmare. Well, I suppose you could pass in a struct as
well, but now we're getting into some really bad coding style territory
;)

S.P.

Sep 29 '06 #3
Snis Pilbor wrote:
Zara wrote:
>>On 28 Sep 2006 20:21:20 -0700, "Snis Pilbor" <sn********@yahoo.com>
wrote:

>>>Howdy,

Forgive me for not looking this up in the manuals or just trying
it outright, as I don't have access to a shell right now. Anyway, I
thought of this while juggling earlier: it would be neat if there were
a way to do a "sizeof" on the total set of declarations at the top of a
given function. For example:

<..>

You may group all of the local variables within a single struct, and
then evaluate sizeof the struct

Zara


Oh hey, you are right Zara, that's a good point. =) Thanks for
bringing it up. But I see some problems with it. The biggest one is
that it doesn't include the memory used by the passed-in arguments: if
my function is "char some_function( char x )", it's going to use at
least 1 byte even if it declares no other memory at all. Though I
guess that's still a big improvement, since one tends to change
passed-in parameters much less frequently than variable declarations,
so one could manually add their sizeof's without quite as big a
maintainance nightmare. Well, I suppose you could pass in a struct as
well, but now we're getting into some really bad coding style territory
We're also getting into territory where compilers as a rule
feel particularly free to apply the "as if" rule. That one byte
you mention might well be in a register and take no stack space
at all. Even an `auto' variable inside a function may spend its
entire lifetime in a register and never be stored in memory.

On the other hand, even register-resident quantities may wind
up occupying stack space during calls to deeper functions or during
interrupt servicing. Some machines will save and restore registers
on every call, some will do a "window turn" and use the stack only
when the call nesting exceeds the window capacity, some will process
interrupts not by stacking anything but by switching to an alternate
register bank, ...

The result of all this variety is that there is no practical
way for a C programmer to get an accurate estimate of his program's
stack use except with reference to a particular implementation; the
next implementation (or the same one under different circumstances)
may use an entirely different amount of stack space. This is too
bad, because it leaves the programmer defenseless against stack
overflow: stack overflow is a characteristic of the implementations,
not of the language. There simply isn't a C-based way of telling
whether a call to foo() might blow the stack, nor a C-based way of
detecting or recovering from the situation should it occur.

The best I can offer is the usual "be sensible and hope for the
best" advice: Avoid creating large variables (usually arrays or big
structs) in `auto' storage, especially in recursive settings. Don't
fret about a few tens of individual variables; just declare them in
a natural manner and give the compiler maximum freedom to make use of
registers and so on. (In particular, sticking a bunch of scalars in
an artificial struct stands a good chance of increasing the amount of
stack space you'll use.) In recursive situations, do the pencil-and-
paper analysis to calculate the maximum (not average!) recursion depth
to get an idea of how parsimonious you need to be. And then hope.

--
Eric Sosman
es*****@acm-dot-org.invalid

Sep 29 '06 #4
The usual gang of cautious Cathys will tell you this is
implementation-dependent, non-portable, causes warts, etc. Here are
two ways to do it, perhaps a bit loopy, but will work on most
platforms. Don't expect it to work on the Rumanian Troika-13, with
it's trinary accumulator and gray-code stack register. This code is
really really useful if you have a lot of threads or signal handlers
and want to monitor and minimize their stack usage.

(1) Log the change in address of the local variables during one
recursion: Something roughly as so:

#define GetAddr -8888
#define GetInfo -9999
int WeRecurse( int x ){ int foo[1000], etc, etc, etc.......; char *
Here; char * Deeper;
unsigned long int Used;

if( x == GetAddr ) // flag to signal we're supposed to address of foo
return (int) &foo;

if( x == GetInfo ) { // flag to signal we're supposed to return size
of activation record
Here = (char *) &foo;
Deeper = WeRecurse( -888 );
Used = abs( Deeper - Here ); .
return( Used );
}

// normal code goes here
}

int main( void ) { int OneActivationSize;

OneActivationSize = WeRecurse( GetInfo );

}

---------------------------------------------------------------------------
(2) A bit dirtier, but does work on many platforms, caveat user:

#define Max 100000 // maybe about twice larger than the expected
activation record size

int PrepareAndSniffStack( char Cmd ) { char TheStack[ Max]; int Depth;
switch( Cmd ) {
case 'i': for( Depth = Max; TheStack[ Depth-- ] = '#'; Depth >= 0 )
;return 0;
case 'q': for( Depth = Max; TheStack[ i ] == '#'; Depth-- )
;return Depth;
}

}

int main( void ) {

PrepareAndSniffStack( 'i' ) ; /// Initialize the stack

TheRoutineToGetInfoOn(); // call the routine you want to measure

Used = PrepareAndSniffStack( 'q' ); /// query the stack usage

Notes:
(a) The info returned is going to include any stack space used by
signals, system calls, and even hardware interrupts (mainly on older
OS's).

(b)On the (very few) machines where the stack grows upward, reverse the
direction of the sniffing loop.

(c) Unlike (1), this one also notices any temporary stack space
allocated by the compiler to call functions that return arrays or
structs.

Sep 29 '06 #5
In article <11*********************@h48g2000cwc.googlegroups. com>,
Snis Pilbor <sn********@yahoo.comwrote:
>Zara wrote:
>On 28 Sep 2006 20:21:20 -0700, "Snis Pilbor" <sn********@yahoo.com>
wrote:
>thought of this while juggling earlier: it would be neat if there were
a way to do a "sizeof" on the total set of declarations at the top of a
given function.
[in order to be able to dynamically adjust recursion limits]
>You may group all of the local variables within a single struct, and
then evaluate sizeof the struct
>Oh hey, you are right Zara, that's a good point. =) Thanks for
bringing it up. But I see some problems with it. The biggest one is
that it doesn't include the memory used by the passed-in arguments: if
my function is "char some_function( char x )", it's going to use at
least 1 byte even if it declares no other memory at all.
As others have pointed out, the size of arguments is implementation
dependant. But that's not a big problem.

As you might be aware, every recursive routine can be rewritten as
an iterative routine, memory permitting.

For example, you can establish a few variables to keep track of
where you are, and then for each new recusion level, you could malloc
a struct containing all the frame variables you might need,
chain the previous frame off of the end of that, set the structure
members that act as inputs, and loop back to near the beginning.
When your code would have returned from a recursion, then figure out
the "return value" (which might not be a simple numeric value), store it
locally for a moment, grab the address of the frame-variables
underneath, destroy the top frame, and continue onwards using the
return value and the newly-exposed frame variables. If there is no
pushed frame left, do your final cleanup and return the return value.
--
If you lie to the compiler, it will get its revenge. -- Henry Spencer
Sep 29 '06 #6

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

Similar topics

4
by: James | last post by:
I have a from with 2 fields: Company & Name Depening which is completed, one of the following queries will be run: if($Company){ $query = "Select C* From tblsample Where ID = $Company...
5
by: Scott D | last post by:
I am trying to check and see if a field is posted or not, if not posted then assign $location which is a session variable to $location_other. If it is posted then just assign it to...
2
by: Nick | last post by:
Can someone please tell me how to access elements from a multiple selection list? From what ive read on other posts, this is correct. I keep getting an "Undefined variable" error though... Form...
2
by: Alexander Ross | last post by:
I have a variable ($x) that can have 50 different (string) values. I want to check for 7 of those values and do something based on it ... as I see it I have 2 options: 1) if (($x=="one") ||...
0
by: Dan Foley | last post by:
This script runs fine, but I'd like to know why it's so slow.. Thanks for any help out there on how i can make it faster (it might take up to 5 min to write these 3 export files whith 15 records...
5
by: Lee Redeem | last post by:
Hi there I've created abd uploaded this basic PHP script: <html> <head> <title>PHP Test</title> </head> <body> <H1 align="center">
5
by: christopher vogt | last post by:
Hi, i'm wondering if there is something like $this-> to call a method inside another method of the same class without using the classname in front. I actually use class TEST { function...
6
by: Phil Powell | last post by:
Ok guys, here we go again! SELECT s.nnet_produkt_storrelse_navn FROM nnet_produkt_storrelse s, nnet_produkt_varegruppe v, nnet_storrelse_varegruppe_assoc sv, nnet_produkt p WHERE...
1
by: Michel | last post by:
a site like this http://www.dvdzone2.com/dvd Can you make it in PHP and MySQL within 6 weeks? If so, send me your price 2 a r a (at) p a n d o r a . b e
11
by: Maciej Nadolski | last post by:
Hi! I can`t understand what php wants from me:( So: Cannot send session cache limiter - headers already sent (output started at /home/krecik/public_html/silnik.php:208) in...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
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: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
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: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
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.