Jump to content


Photo
- - - - -

A horrible bug....


77 replies to this topic

#61 Tim Woodall

Tim Woodall

    Member

  • Members
  • PipPip
  • 20 posts

Posted 25 July 2001 - 02:12 PM

>'C arrays are always passed by reference'
p.371 Programming Language Pragmatics, Michael L Scott, Morgan Kaufman, 2000

WG14/N869 Committee Draft - January 18, 1999 (sorry I don't have the final version to hand)

6.3.2.1 Lvalues and function designators

3. Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type 'array of type' is converted to an expression with type 'pointer to type' that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behaviour is undefined.

6.7.5.3 Function declarators (including prototypes)

6. A parameter list specifies the types of, and may declare identifiers for, the parameters of the function. A declaration of a parameter as 'array of type' shall be adjusted to 'pointer to type', and a declaration of a parameter as 'function returning type' shall be adjusted to 'pointer to function returning type', as in 6.3.2.1. [...]

(typos are copyright me :-)

Therefore the C standard explicitly states that arrays are not passed to functions (by reference or otherwise), instead a pointer to the first element of the array is passed (by value).

#62 Tim Woodall

Tim Woodall

    Member

  • Members
  • PipPip
  • 20 posts

Posted 25 July 2001 - 04:56 PM

(The attachment is to allow me to post - it doesn't have anything very interesting in it!

>Then I think it better practice for a caller to say
>MYGLOBAL(1, #R1, #unused, #unused
>than to sa
>MYGLOBAL(1, #R1, 0, 0


Maybe. Personally I prefer the zero method, expecially as someone is bound to assume that #unused has the value 0 and a bug in the application will change it. (Of course someone might assume that 0 has the value of 0 and a bug in the application might change it :-) but we can fix this using a copy

>Any chance of this happening then
I expect that the copy of literals for global logics will be implemented. This ought to be a fairly simple job because of the pass by reference parameters. It probably won't be straight away though and it won't be a bug fix. Maybe an enhancement or should that be dehancement :-

Global Functions are slightly more tricky and I expect that it will stay with a gen warning. Of course, whoever has that spare day or so to 'fix' and test the global logics may discover they have time to do this copy implementation as well. I think this will be more difficul
to get right but there are several approaches I can think of to resolving this one other than the copy which may prove to be simpler

The duplicate names for parameters requires some careful thought. If it is going to be 'fixed' it should be fixed 100% and not 97.8%. Just trying to document exactly what does happen and what should happen is hard enough

Unfortunately, in this instance ProIV has given people too much rope (unnecessarily - I think this is a gen time change and therefore the historical problems of processor speed are not so applicable) and there is always the possibility of someone relying on some 'feature' that should never have been permitted

Furthermore, IMNSHO it doesn't make sense to pass the same variable twice as an Output parameter (and/or Both) but you have suggested that to use #unused, #unused is preferable to 0,0 therefore to implement what I think makes sense would break what you think makes sense

So

If you pass the same variable twice as output parameters should you get a gen warning? - this will annoy you if you do it much - I don't expect that anyone would but then I wouldn't have considered using #unused in place of

If you pass the same variable twice as output parameter
should you get a gen error? - I wouldn't write code like this intentionally so it wouldn't worry me :-

If you pass a literal as an output parameter should you get a gen warning? I am willing to accept this. If I do it deliberately then I can put up with the warning. If I do it accidently then I would prefer to find out now rather than later :-
Note: I think you should get a gen warning regardless of whether the copy is implemented. Maybe you should be able to turn it off but it is as likely that you put the 0 in the wrong place as to do it deliberately

If you pass a literal as an output parameter should you get a gen error? This would annoy me as I can think of circumstances where 'code reuse' implies that this would be a sensible thing to do but you would tell me to use #unused
Note: it might make sense to document that the only literal that can be passed to an output parameter is 0 and generate a gen error for any other value. Obviously this isn't as simple for both parameters

#63 Richard Bassett

Richard Bassett

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 696 posts
  • Location:Rural France

Posted 25 July 2001 - 05:12 PM

>Therefore the C standard explicitly states that arrays are not passed to functions (by reference or otherwise), instead a pointer to the first element of the array is passed (by value).
I don't actually agree it says 'arrays are not passed to functions'. All it does is state the coercion (or is that cast or conversion...) to be applied so that you can use all the array and pointer operations (including pointer modification) on a formal parameter which is declared 'array of type'.

Just saying 'arrays are not passed' period is avoiding the issue really. The value IN the array is accessible in the called function. I realize we may be heading for disagreement over the use of natural language here but bear with me...

Suppose I repeat my example code with the C char[] syntax replaced with a hypothetical string datatype with the SAME SEMANTICS (maybe I could do this with a typedef but I don't know how right now):

int l;
string greeting = 'Hello World'; // was char greeting[] = 'Hello World';
l = strlen(greeting);

int strlen(string str) // was int strlen(char str[])
{ int i = 0;
while (!(str[i] = ''))
i = i plus 1;
return i;
}

Then the appearance AND behaviour of this code is pure call-by-reference, just like ProIV global logic.
You are programming as if the string (the C ARRAY as it was) was passed by reference. Clearly the string value 'Hello World' is not passed by value.

So if you take the view that the ARRAY is passed (which I and Prof. Scott presumably do and I guess you don't) then you have to say that the ARRAY is passed by reference, nothing else makes sense.

In fact, putting an address (pointer value) on the stack is probably the most obvious way to implement call by reference (although in that case of course you wouldn't allow changing the value of the pointer!)

So, anyway, to labour the point, if you look at it FROM THE POINT OF VIEW OF THE VALUE OF THE STRING it is call by reference except that you can additionally use pointer operations on str and even change where it points if you want to (because the C mindset and programming style 'equates' arrays and pointers so that's what programmers expect).

I CAN understand where you're coming from but it does seem to me a very implementation-centric point of view.
Nothing's as simple as you think

#64 Richard Bassett

Richard Bassett

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 696 posts
  • Location:Rural France

Posted 25 July 2001 - 06:21 PM

Hmm…

What does 'it won't be a bug fix. Maybe an enhancement' mean to the people who want it? Do we need to take specific action to make sure this appears in v4.x? Are you suggesting it might be a chargeable RPQ?

Firstly, and most importantly, the (well my anyway) objective was a guarantee that literals could not be corrupted. To that end I would be MUCH happier to see call-by-value (copy-in) implemented for all literals passed to global functions.

If that didn't happen, I personally would want literals passed as O or B type parameters to be a gen (not DS or VIP) error (not warning). As has been pointed out this may well upset lots of people with existing code so the silent implementation of call by value is a MUCH better solution.

I personally agree with you that an OPTIONAL gen WARNING even when the copy-in is implemented is worth having.

I'm not hung up on the #unused thing, I can live with 0 perfectly well provided it's guaranteed incorruptible. I've never done this for a global function anyway, only for global logic.

You're quite right that my #unused style is a problem if/when there is warning for using the same 'target' argument more than once. I'd rather have that warning and use the zeroes but I really don't mind if it never happens. This issue is massively less important than protecting the literals. Effort spent on this would be much better spent implementing call-by-value literals for global functions.

You're also right about bugs arising in called code (inadvertently) dependent on #unused being zero - the hypothetical NULL mentioned below would be better from that point of view. Generally I actually name my global logic parameters #OUT_result1 or such to try and improve my chances of spotting such errors - it's not a particularly satisfactory state of affairs but it was much better than 1=0!

Of course, it would be nice to have some kind of direct support for a variable number of arguments (which is what the example is simulating right?) or (perhaps not so good) a NULL or some such keyword which would behave like a NULL pointer in C and cause a runtime error if called code tried to read or write that target (which obviously it should not be doing). I know these are way outside the ProIV framework and I don't even pretend I've thought through all the ramifications so let's not pursue it :-)
Nothing's as simple as you think

#65 Tim Woodall

Tim Woodall

    Member

  • Members
  • PipPip
  • 20 posts

Posted 25 July 2001 - 07:05 PM

>string greeting = 'Hello World'; // was char greeting[] = 'Hello World'
> l = strlen(greeting)

> int strlen(string str) // was int strlen(char str[]


I think we are starting to argue about irrelevant issues at least as far as ProIV goes but I will try to explain why it is wrong to think of arrays as passed by reference even though it appears to a casual glance that they are

Pass by reference does not have to be implemented as a pointer. It is perfectly possible to pass a 'handle' that has no direct relevance to memory at all. (This can be useful in distributed processing

The C standard states[1] that any compiler may invoke the 'as is' rule which basically says that a compiler writer can implement anything in any way she choses so long as the final result is indistinguishable from an implementation that does exactly what the standard states

Now if arrays were passed by reference in C it would be possible to design a compiler that allowed a handle to be passed to a function where arrays are passed

in main.
extern int strlen(char str[])
l = strlen(greeting)

in call.
int strlen(char* str



This clearly cannot be implemented using a handle because the compiler may never see both definitions[2]. If you really want to be perverse, compile the two files on two different PCs and link it on a third

[1] To be honest, I only know that this rule exists in the Cpp standard but I assume it exists in the C standard

[2] To preempt the 'well you could always pass a handle instead of a pointer' we are back to where we started from and casting pointers just becomes almost impossible.

#66 Richard Bassett

Richard Bassett

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 696 posts
  • Location:Rural France

Posted 25 July 2001 - 09:34 PM

This stuff is certainly irrelevant as far as ProIV is concerned, hence my 'incurable C programmers only' tag. It is also hurting my brain so we have to stop.

All I'm saying is I can write a C program, using arrays but not pointers that looks like, behaves like and is likely even implemented like some other language that does not have pointers and which you would (probably) be happy to say passes arrays by reference.

For me that's good enough to say C passes arrays by reference. I wouldn't disagree that it's 'by reference with knobs on' because of the way C lets the programmer treats the 'array' variable as a pointer.

It's the C specific 'knobs' that constrain the compiler writer where the actual and formal arguments are of array type. For me that doesn't stop it being call by reference. I think the 'handle' argument is a little bit specious.

Anyway, I think we both know exactly what's really going on in C so I'm going to leave it at that - as you say it doesn't belong in this forum anyway.
Nothing's as simple as you think

#67 Rob Atherton

Rob Atherton

    Member

  • Members
  • PipPip
  • 43 posts
  • Gender:Male
  • Location:Sweden

Posted 26 July 2001 - 07:34 PM

Wow, that one caused a bit of a reaction, didn't it.

Anyway, my brain exploded about 2 days ago after reading all that so I've just got 2 questions:

0. Does 1 still equal 0 or not ?

6. If it does and we want 1 to equal 1, are we going to have to pay for it or not ?

Thanks........

#68 Chris Pepper

Chris Pepper

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 369 posts
  • Gender:Male
  • Location:United Kingdom

Posted 27 July 2001 - 06:18 AM

I'm just an analyst type who got into PRO-IV to get things done and I don't really understand much about compiler writing and all this 'C' stuff.
(I do know that if I was Tim Woodall I would have used a couple of CONTINUE statements in his CASE statement!) - but that's a PRO-IV way of coding it!

The PRO-IV manual tells me that PRO-IV has constants, variables and operations.
I don't know if I'm just being simple here... but all I expect is that a constant is just that!!! I'm not sure what else 'constant' means?
Using the word 'constant' for 'variable initialised to a value by the gen process which can then be modified' is just not a part of the English language I understand. Perhaps we should change this bit of the manual to call them 'semi-constants'?

#69 Glenn Meyers

Glenn Meyers

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 221 posts
  • Gender:Male
  • Location:St. Louis, MO, United States
  • Interests:I also raise African Gray Parrots and build hot rod automobiles.

Posted 30 July 2001 - 11:49 AM

Murphy's Law
Collary 213

All cnostants aren't.

#70 Glenn Meyers

Glenn Meyers

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 221 posts
  • Gender:Male
  • Location:St. Louis, MO, United States
  • Interests:I also raise African Gray Parrots and build hot rod automobiles.

Posted 30 July 2001 - 11:50 AM

Murphy's Law
Collary 213

All constants aren't.

#71 Ralph Gadsby

Ralph Gadsby

    Expert

  • Members
  • PipPipPipPip
  • 154 posts
  • Gender:Male
  • Location:United Kingdom

Posted 31 July 2001 - 09:46 AM

OK, as I stated right at the start of this thread, this is NOT a bug.

I left it at that just to see how long it would be before someone would realise that to fix this 'problem' would be an enhancement. I am amazed at how long this thread continued before someone actually stated this - and it is Tim that gets the prize. The code that exists works as intended, therefore it cannot be a bug.

ProIV uses call by reference as it is the most efficient way of accessing variables in a called process, both in terms of processor cycles and in memory usage. At the time this was implemented this was important, as processors were much slower and memory was very expensive. Times have changed.

If someone wishes to log this as an enhancement it will no doubt get the attention that it deserves.

#72 Steve Jenkins

Steve Jenkins

    Advanced

  • Members
  • PipPipPip
  • 58 posts
  • Gender:Male
  • Location:Cardiff, United Kingdom

Posted 31 July 2001 - 10:11 AM

Thanks for that Ralph.

I think everybody agrees with you. This is not a bug it is an enhancement. Just as, 1 does equals 0, Elvis lives and the Pope's real name is Leeroy Brown and he's from Brooklyn.

Anybody disagree with any of those statements? If so, tough luck. I'm standing by them no matter what evidence is thrown before me. If you want me to change my mind you need to pay me.

#73 Joseph Serra

Joseph Serra

    Advanced

  • Members
  • PipPipPip
  • 93 posts
  • Gender:Male
  • Location:Melbourne, Australia

Posted 31 July 2001 - 10:13 AM

tr>


I don't know if you are familiar with the latest ProIV website, but they have such a great logo there...'Focus on the business not the technology' on a nice pretty globe.

Well that is exactly what we are doing, 1 does not equal 0. I don't care if it is a bug, enhancement or whatever. Just tell me when 1 = 1.

#74 Rob Atherton

Rob Atherton

    Member

  • Members
  • PipPip
  • 43 posts
  • Gender:Male
  • Location:Sweden

Posted 31 July 2001 - 10:52 AM

Ralph,

Quote: 'I left it at that just to see how long it would be before someone would realise that to fix this 'problem' would be an enhancement.'

I did not say that this should be a chargeable enhancement to make 1=1, I asked if we would have to pay for it.

I assume that you meant to write 'change' instead of 'fix' as fix implies it was broken in the first place or does FIX=CHANGE ??

JFDI

#75 jerrywills

jerrywills

    Newbie

  • Members
  • Pip
  • 4 posts
  • Gender:Male
  • Location:Virginia, USA

Posted 31 July 2001 - 04:35 PM

Isn't the definition of conclusion - the FINAL word - or does 'CONCLUSION'='CARRY ON THE THREAD' ??



Reply to this topic



  


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users