|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Display Modes |
|
#1
|
|||
|
|||
|
another way to shoot yourself in the foot?
Consider a very simple code. Suppose we have
1) a Named interface as this named.ads package Named is type is limited interface; function name(this: ) return String is abstract; end Named; 2) Simple implementation Some.ads with Named; with Ada.Finalization; use Ada.Finalization; with Ada.Strings.Bounded; package Some is Size : constant := 80; package bs is new (Size); use bs; type is new Limited_Controlled and N with private; function Create( name: String ) return ; overriding procedure Initialize(this: in out ); overriding procedure Finalize(this: in out ); overriding function name(this: ) return String; private type is new Limited_Controlled and N with record the_name: Bounded_String; end record; end Some; Some.adb with ada.Text_I; package body Some is package tio renames ada.Text_I; function Create( name: String ) return is begin return : do := To_Bounded_String(name); end return; end Create; procedure Initialize(this: in out ) is begin tio.Put_Line("Initialization Car " & this.name); end Initialize; procedure Finalize(this: in out ) is begin tio.Put_Line("Finalization Car " & this.name); end Finalize; function name(this: ) return String is begin return To_String(this.the_name); end name; end Some; 3) Simple factory function as follows: Factory ads with Named; with Some; package Factory is function Create(class: String; name: String) return N'Class; end Factory; Factory.adb with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Some; package body Factory is this one is ugly, but in sake of simplicity function Create(class: String; name: String) return N'Class is begin if Index(class, "Some") /= 0 then return Some.Create(name); end if; raise Program_Error with "Unknown class " & class; end; end Factory; 4) And finally main procedure boom.adb with ada.Text_I; with Named; use Named; with Factory; with Some; procedure boom is package tio renames ada.Text_I; aNamed: S := Some.Create(""); begin declare aNamed1: N'Class := Factory.Create("Some", "Two"); begin tio.put_line( "car: " & aNamed1.name ); !!! end; tio.put_line( "car: " & aNamed.name ); tio.Flush; end boom; All of that being compiled without even one warning, crashed at runtime with PRGRAM_ERRR EXCEPTIN_ACCESS_VILATIN on Windows ( compiled using gnat gpl 2008 ) Modified program ( N, being changed to be not limited, and S to be Controlled ) runs perfectly. I have an idea why the program behavs like that, but i think there must be some warning at least. What do you think? |
|
#2
|
|||
|
|||
|
another way to shoot yourself in the foot?
I thought it's some type of narrowing problem but anyway you're
right, it seems very match as compiler bug Anyone willing to reproduce this bug with GCC 4.3 and report it to Bugzilla if applicable? -- Ludovic Brenta. |
|
#3
|
|||
|
|||
|
another way to shoot yourself in the foot?
Robert A Duff writes:
But in Ada 95, if you say: > P(F()); > where F returns limited, you are not passing a limited object, but an implicit reference to some object that already existed before the call to F. [] In Ada 2005, functions always return newly-created objects, which I think is appropriate. This makes me wonder whether there is an actual difference in the way the compiler handles such returns. For example, has GNAT changed a lot in this area? Do the Ada 95 and Ada 2005 compatibility modes use antirely different compilation strategies? if F().Flag then > The last one is pretty silly -- it creates a new limited object, grabs a boolean flag out of it, and then throws the whole thing away. Yes but "grabbing a boolean flag" might consist in passing the limited object as a parameter to a primitive function named Flag, which might then pass it down to any number of subprograms with all sorts of side effects. could write an arbitrarily large program like this :) -- Ludovic Brenta. |
|
#4
|
|||
|
|||
|
another way to shoot yourself in the foot?
Dmitry A. Kazakov wrote:
The enclosing object does not expect its components to prematurely finalize themselves. It is just a bad design turned upside down: It seems like everyone wishes to force dynamic context information to be expressible as static type features, together with implicit callback operations from Controlled'Class. Why not use plain old scopes when establishing context for objects? generic elaboration. Is anything wrong with having all of lifetime, startup and cleanup of objects controlled by a combination of: nesting, making calls, handling exceptions, and scoping? Would Finalize be superior when calls from within it will have to refer to all kinds of other data anyway, even indirectly? The Controlled subprograms are linked to a single type. From what I know about Aspect Programming, it shows that building modules around a single type does not always yield the right abstraction: When the thing is seen from a different angle, the type should have a different interface. From yet another viewpoint, the type's operations should cooperate differently. In still another perspective some abstraction is not represented by this type alone. Instead, it would be represented by some combination of this type and another type. And now automatic operations like Initialize and Finalize, hooked on a single type (and possibly discriminants GNAT like at last :-) are supposed to be the solution of all data management? |
|
#5
|
|||
|
|||
|
another way to shoot yourself in the foot?
Ludovic Brenta wrote:
Robert A Duff writes: > >if F().Flag then >> >The last one is pretty silly -- it creates a new limited object, >grabs a boolean flag out of it, and then throws the whole thing >away. > Yes but "grabbing a boolean flag" might consist in passing the limited object as a parameter to a primitive function named Flag, which might then pass it down to any number of subprograms with all sorts of side effects. could write an arbitrarily large program like this :) A simple one crossed my mind immediately, if Earth().Result = 42 then |
|
#6
|
|||
|
|||
|
another way to shoot yourself in the foot?
Dmitry A. Kazakov schrieb:
>And now automatic operations like Initialize and Finalize, >hooked on a single type (and possibly discriminants >GNAT like at last :-) are supposed to be the solution of >all data management? > Yes they are. Note that constructing/destructing hooks have different rules of composition, like aggregates and assignments have. They are not overridden they are extended. (Ada's Finalization is bogus, alas). Just one point ad hoc. Taking the notion of construction further, define the concept of initialization. In general, initialization of an object of type T1 may logically be related to the observable state of of type T2, where observable state means result of operations or (component) values. As these states change while a program is running, the dependences may not always be the same. 's initialization may logically depend on F(, , N), or more generally on F(G_1(, , M_1), G_J(J, , M_J)). for some finite sets of objects and functions. Basically, on anything that can be programmed into an expression used for initializing. It may be cross unit, involve P98.T19 or not, or A.B.T42 only if G_17() 666 etc. This "net of dependence" would mean that a constructor will have to adjust its behavior to the current state of the program. Adjustment may be realized through dispatching to a load of objects, other constructors, etc. etc. etc. IW, every constructor becomes a huge factory in disguise. It has to perform case distinction. How is this seemingly special construction different from just normal programming? The only added value of constructors that I can see is that I can point to a few functions which "point to" all this. A good addition, and not a small one. But should we therefore abandon all other means of initializing things? If construction turns out to be mostly normal programming, why not use plain old language features in addition to specialized constructor programming? For example, use local scopes and visibility for providing (computed) initial values, even though a scope is not an operation of a type, like a construtor function is. |
|
#7
|
|||
|
|||
|
another way to shoot yourself in the foot?
SNIP:-
>Why does Gary Scott's company use almost entirely C++ if Gary Scott recommended Fortran? I have met this situation many times. As an example, a very large Company first wrote its accounting software n 1961 in Fortran, using integer arithemetic and separate tracking of cents or pennies, on an IBM 1401 (after using plugboard hardware). This included payroll. Later, following IBM advice they took the PL/1 route after first deviating via Cobol (and RPG and Mark4 !). Very much later, Cobol, PL/1 and Fortran programmers became hard to find, so the C and C++ languages were adopted after a look at Ada and much talk with Borland. Basic was considered and actually used for quick "stuff". Meanwhile I kept on updating the Fortran compilers and the BMD and BMDP mathematical packages (which are/were Fortran IV source code). The points to consider always are:- a) what the programming gurus" on staff think are the best options, b) what the personnel staff say are the long-range availability of programming candidates and prices, c) what the universities and technical colleges have decided to teach for problem-solving, especially to electrical, engineering and geophysical/geology and mining students. What a company finally decides on, can differ, even when competing in the same fields. And so long-term computer expert staff may know one language is far better for the company's future, through years of exposure and use of alternatives, yet have to bow to instructives based on economic forces. solution I was not able to implement, was to take any new programmers willing and available, and re-teach them a reasoned, chosen and company-wide imposed language, which would have been Fortran IV (over PL/1 by a hair) and of course going to F90 as soon an F95 became available, one sure step behind. I DID manage to get the concept accepted of hard-disk computer workstations instead of terminals and maninframes well before it became glaringly obvious as cheaper and more flexible. Intercommunication was via minicomputers as message and file-passing nodes and central file back-up and archiving points. |
|
#8
|
|||
|
|||
|
another way to shoot yourself in the foot?
**** Hendrickson wrote:
Colin Paul Gloster wrote: >> >Does Fortran always automatically check if the INTERFACE actually >corresponds to the code? >> Depends on the compiler, but in general N I think all compilers will detect an explicit assignment to a dummy argument that has INTENT(IN) in the subroutine; I'm not sure any will detect an assignment if the dummy is passed on to another routine and that routine (illegally) assigns to its argument. Is that actually possible without lying about an interface? i.e. Is it possible to pass an INTENT(IN) dummy as an actual argument to a more permissive dummy argument in another routine (no intent or intent UT) |
|
#9
|
|||
|
|||
|
another way to shoot yourself in the foot?
Craig Powers wrote:
**** Hendrickson wrote: >Colin Paul Gloster wrote: Does Fortran always automatically check if the INTERFACE actually corresponds to the code? >Depends on the compiler, but in general N I think all >compilers will detect an explicit assignment to a dummy >argument that has INTENT(IN) in the subroutine; I'm not sure >any will detect an assignment if the dummy is passed on >to another routine and that routine (illegally) assigns to >its argument. > Is that actually possible without lying about an interface? i.e. Is it possible to pass an INTENT(IN) dummy as an actual argument to a more permissive dummy argument in another routine (no intent or intent UT) It's not permitted. The standard doesn't require implementations to verify that it's not done. That is, it's not one of the kinds of error that the standard requires implementations to detect and report. -- J. Giles "I conclude that there are two ways of constructing a software design: way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies." -- C. A. R. Hoare "Simplicity is prerequisite for reliability" -- E. W. Dijkstra |
|
#10
|
|||
|
|||
|
another way to shoot yourself in the foot?
**** Hendrickson wrote:
Colin Paul Gloster wrote: >Are "there are a number of things the Fortran standard leaves >unspecified that it should pin down"? >> Sure, Maybe, No. Take your pick. Generally, I'd say no. I think the balance between execution speed, compile time checking, and user responsibility is pretty good. The above is a direct quote from one of my articles and is *way* out of context. Yes, there are a number of things the Fortran standard leaves unspecified that it should pin down. For example (and I think this is the original context), integer arithmetic should be exact if it doesn't overflow. No one would accept an implementation that did otherwise, but the standard should actually require it. Many other languages also don't explicitly require such things. I'm not certain that Ada does. -- J. Giles "I conclude that there are two ways of constructing a software design: way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies." -- C. A. R. Hoare "Simplicity is prerequisite for reliability" -- E. W. Dijkstra |
|
#11
|
|||
|
|||
|
another way to shoot yourself in the foot?
James Giles wrote:
Craig Powers wrote: >**** Hendrickson wrote: Colin Paul Gloster wrote: Does Fortran always automatically check if the INTERFACE actually corresponds to the code? Depends on the compiler, but in general N I think all compilers will detect an explicit assignment to a dummy argument that has INTENT(IN) in the subroutine; I'm not sure any will detect an assignment if the dummy is passed on to another routine and that routine (illegally) assigns to its argument. >Is that actually possible without lying about an interface? i.e. Is >it possible to pass an INTENT(IN) dummy as an actual argument to a >more permissive dummy argument in another routine (no intent or >intent UT) > It's not permitted. The standard doesn't require implementations to verify that it's not done. That is, it's not one of the kinds of error that the standard requires implementations to detect and report. > You're partially wrong, James. It is permitted to pass a dummy with INTENT(IN) to a subroutine that doesn't specify either INTENT(INUT) or INTENT(UT). You can pass them to a subroutine that doesn't specify intent and even potentially modifies its argument. You can't lie in an interface, but you can call routines that don't have an interface. Those routines are required to do the right thing; but the compiler isn't required to detect violations. **** Hendrickson |
|
#12
|
|||
|
|||
|
another way to shoot yourself in the foot?
James Giles wrote:
Craig Powers wrote: >**** Hendrickson wrote: Colin Paul Gloster wrote: Does Fortran always automatically check if the INTERFACE actually corresponds to the code? Depends on the compiler, but in general N I think all compilers will detect an explicit assignment to a dummy argument that has INTENT(IN) in the subroutine; I'm not sure any will detect an assignment if the dummy is passed on to another routine and that routine (illegally) assigns to its argument. >Is that actually possible without lying about an interface? i.e. Is >it possible to pass an INTENT(IN) dummy as an actual argument to a >more permissive dummy argument in another routine (no intent or >intent UT) > It's not permitted. The standard doesn't require implementations to verify that it's not done. That is, it's not one of the kinds of error that the standard requires implementations to detect and report. Actually, that's not exactly right. It's not permitted to pass an INTENT(IN) to a dummy with intent UT (i.e. INTENT(INUT) or INTENT(UT)), this is a constraint in 5.1.2.3 in the F95 draft as well as constraint C545 in the F03 draft, so I think it would require a diagnostic. However, it IS permitted to pass an INTENT(IN) to an unspecified INTENT dummy, and in that case it would be possible to modify it (and I wouldn't expect a compiler to even realistically be able to detect that except in very specific circumstances). |
![]() |
| Viewing: Web Development Archives > FAQs > Programming > another way to shoot yourself in the foot? |
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|
|
|