http:^^www.cs.washington.edu^homes^jbaer^layers.html

来自「This data set contains WWW-pages collect」· HTML 代码 · 共 375 行 · 第 1/2 页

HTML
375
字号
Date: Tue, 10 Dec 1996 23:17:33 GMTServer: NCSA/1.4.2Content-type: text/htmlLast-modified: Tue, 04 Jun 1996 08:02:30 GMTContent-length: 15262<html><title>Static Layer Analysis for C Programs</title><body><h1 align = center>Static Layer Analysis for C Programs</h1><p><br><br><p>Jeremy Baer<br>Department of Computer Science and Engineering<br>University of Washington<p><br><p><b>Abstract</b><p>Principles of a hierarchical or layered approach to software designare discussed.  Preliminary work on software tools to allow both theenforcement of a layered structure during forward engineering, andthe extraction of layered structure from pre-existing C languagesource code is presented.<p><br><p><b>Introduction</b><p>The idea of layered design is not new to software engineering.  In1979 Parnas wrote about building software as layers of virtualmachines, and defined the "uses" relation for components in a softwaresystem [P79].  In this paper, he advocates a hierarchical designapproach in which no component in level 0 uses any other component andeach component in level <i>i</i> of the hierarchy uses at least onecomponent in level <i>i</i> - 1 but no component at a level higherthan <i>i</i> - 1.  The "uses" relation itself is defined such thatcomponent A uses component B if the correct operation of A dependsupon the existence of some correct implementation of B.  Parnas arguesthat if a system is built in such a way that a uses hierarchy existsfor its components, then each level of that hierarchy comprises ausable subset of the complete system.  Clearly this is a desirableproperty for a system to have, particularly from the perspective ofcode reuse and system development in which "families" of similarsystems are to be developed from the same code base. <p>Another design methodology which Parnas has also written in support ofis information hiding [P72][P79].  Information hiding and hierarchical orlayered design structure are essentially orthogonal to one another,and both seem to be valuable techniques which can be applied toproblems in software engineering.  However, while considerablelanguage support has been developed for information hiding (there area plethora of object-oriented and object-based languages which allowthe enforcement of information hiding), little work has been done withregard to language support for layered systems.  This paper presentssome preliminary work on two tools (<b>lcc</b> and <b>lce</b>) toallow both the enforcement of a layered structure during forwardengineering, and the extraction of a layered structure (if one exists)from pre-existing C language code.  These tools do not utilize Parnas'"uses" relation for establishing layers.  Instead they work with thesimpler "invokes" relation.  As Parnas points out, although invokesand uses often coincide, they are not identical.  Component A may<i>invoke</i> component B but not actually depend on the correctnessof B for its own correct operation.  Similarly, component A may<i>use</i> component B without ever directly invoking it.  A simpleexample of this might be if components A and B communicate through thesetting and reading of global variables.  The invokes relation waschosen for simplicity of implementation, and its direct applicabilityto both forward and reverse engineering.  Computing whether a useshierarchy exists for a collection of source files would seem torequire that one have access to a fairly precise specification of thesystem's components -- in order to determine whether the correctoperation of component A depends on component B, we must know what thecorrect operation is.  Thus, in order to enable a feasibleimplementation of the tools discussed in this paper, it was decidedthat they would operate on layers over the invokes relation.<p><br><p> <b>Layered C Checker (lcc)</b> <p> lcc is a simple tool intended for use in a forward engineeringcontext, in which the enforcement of a layered design structure on thedevelopment of source code is desired.  lcc checks an annotated Cprogram to determine whether or not level boundaries assigned tofunctions are maintained.  It can be set to allow recursive functions,since recursive functions would normally be reported as an error (afunction which calls itself is calling a function on the same level asitself, which is contrary to normal layered structure).  Additionally,some flexibility may be desired in the number of layers whichinvocations can cross before lcc reports them as errors.  The strictdefinition of a layered system in which a function at level <i>i</i>can only call functions at level <i>i</i> - 1 may be easily attainableat an abstract level by inserting "dummy" functions at the interveninglayers across which a multi-layer invocation would otherwise reach,but it is typically not desirable to introduce lots of functions inthe source code itself whose only purpose is to call other functions.Thus, lcc may be instructed to allow invocations to cross <i>k</i>layers.  There is also an option to allow an invocation to cross anynumber of layers (so long, of course, as it is going from a higherlevel to a lower level).<p>lcc utilizes a very simple (and fairly ad hoc) parsing mechanism bothto recognize the annotations and to extract the call graph fromsource.  The call graph extractor is perhaps overly simplistic.  Itbuilds a graph based solely on tokenized function calls whose textualnames match one of the functions which is declared in the source.  Asa result, it completely ignores any invocations which occur throughthe use of function pointers.  It also performs no reachabilityanalysis on the code, and may thus include invocations which can neverhappen.  These comments also apply to lce, which will be discussedlater.<p>Following is some sample output of running a version of lcc on asimple program which does not have a strict layered structure, followedby a run of lcc on itself (it turns out that lcc itself does have astrict layered structure):<pre>896 cindy:layered_c >lcc -2 -l -r foo.cFunctions by level:level 1    foo.c: my_abs    foo.c: my_fact    foo.c: i_power    foo.c: d_powerlevel 2    foo.c: my_cos    foo.c: my_explevel 3    foo.c: my_funclevel 4    foo.c: find_rootlevel 5    foo.c: mainfoo.c: Illegal level crossing:    my_abs (level 1) invoked from find_root (level 4)foo.c: Illegal level crossing:    my_abs (level 1) invoked from main (level 5)foo.c: Illegal level crossing:    my_abs (level 1) invoked from main (level 5)Exiting with errors 897 cindy:layered_c >lcc -l lcc.ccFunctions by level:level 1    test.cc: FunctionLookup    test.cc: nextTokenStrlevel 2    test.cc: HandleError    test.cc: FindFunctions    test.cc: CheckLayerslevel 3    test.cc: mainAll level boundaries are maintained!  Cool!</pre><p><br><p>There are two different approaches which may be taken with respect tohow annotations are done in lcc.  One approach is to make lcc anintegral part of the compilation process.  In this approach, a specialkeyword (@level) is added to C in order to allow the assignment oflevels to different functions.  Directly after each functiondeclaration (before the function body), the @level keyword mustappear, along with a numeric level assignment.  For example:<pre>int foo(double x) @level 3{    <i>function body</i>}</pre><p>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?