Bug in wimp.h

Chris Rutter chris at willow.armlinux.org
Wed Aug 23 19:57:16 BST 2000


On Mon, 21 Aug 2000, Jonathan Coxhead wrote:

>  | The compiler's perfectly at liberty to feed you back nm[0] == '*' and
>  | nm[1] == '\0' after that call, when clearly those memory locations will 
> have
>  | been updated.
> 
>    Actually, it can't. The inside of wimp_load_template() (if written in C) 
> would be completely within its rights to contain code like this:
> 
>       wimp_load_template (..., char const *name, ...)
>       {
>          char *name_var = (char *) name; /*cast away const*/
>          name [0] = ...;
>       }
> 
> and indeed, that's pretty much what it does.

Well, I'm aware that you can perform a const-removing cast and then
write away, but don't you run the risk of invoking undefined behaviour?

I must have misunderstood the purpose of `const': in simple terms, I
thought it was, amongst other things, to allow a function to declare
`I don't modify the the object this pointer points to', so that the
caller doesn't have to flush any cached values held in local/register
memory from that object.

If this guarantee doesn't hold in this way, then what /is/ the purpose
of `const'?

It's tempting to answer with a tautology (`because you might receive a
`const' argument and won't be able to use it with the function'), but
please don't. :-)

>    But there *is* a problem, and here it is:
> 
>       char const nm [12] = "*";
>       wimp_load_template (..., nm, ...);
> 
> Here, |nm| is actually const. It could be allocated in read-only memory, 
> for example. So casting away const inside is illegal. (In the first 
> example, |nm| was a variable.) Of course, the inside of the function has no 
> way of knowing whether its argument is "really" const or not, which is why 
> casting away const is a bad thing to do. Nevertheless, it is legal code.

Yes, precisely!  This is the point I was trying to make.  Follow this
chain of reasoning:

  * String literals are nonwritable in ANSI C.

  * It is most /definitely/ legal to pass a string literal to a standard
    library function which declares that it takes a `const char *'.

  * Therefore (and this is the tenuous step), all functions which, for
    example, declare that they take a `const char *' guarantee that they
    /will not/ write to the memory the passed pointer refers to.

  * /Therefore/, a caller function is at liberty to assume that the values
    contained in an object passed to a function as `const' will remain
    /unmodified/ after the call to the function.

  * Thus, if you cast away `const', you're risking breaking assumptions made
    elsewhere in the code.

Hence my original point: in this code:

    const char nm[12] = "*";
    wimp_load_template(..., nm, ...);
    printf("%c\n", nm[0]);

you can legally get the output `*', /even if/ `nm[0]' has been modified
to contain another value by the innards of wimp_load_template().

I suspect I may have misunderstood the `const guarantee': could you explain
where my reasoning falls down?

>    Even it broke code, we would still fix it, because the current situation 
> is a bug, and we don't care about bug-compatibility; only feature- 
> compatibility.

Very noble point of view.

Is there any analysis of the average space taken by OSLib veeners in
OSLib-using RISC OS applications?  (I'm wondering whether it would be
worth DLLization.)
          ^[1]
c.

[1] An Americanism. ;-)




More information about the oslib-user mailing list