Is an address change possible by "deconstify/const_cast"?

Discussion in 'C Programming' started by Markus.Elfring@web.de, Jul 9, 2005.

  1. Guest

    I am interested to know if the pointer value for the memory address can
    be changed by a compiler if the constness of the corresponding type is
    cast away.

    inline char* deconstify1(char const * X) { return (char*) X; }
    inline char* deconstify2(char const * X) { return const_cast<char*>(X);
    }

    const char source [] = "Test";
    char* alias1 = deconstify1(source);
    char* alias2 = deconstify2(source);

    if ((source != alias1) || (source != alias2) || (alias1 != alias2))
    { printf("unequal: %p %p %p", source, alias1, alias2); }

    Can this happen on a current platform?
    Does any tool try to copy the data to a read-only area to achieve any
    protection?

    Regards,
    Markus
     
    , Jul 9, 2005
    #1
    1. Advertising

  2. Eric Sosman Guest

    wrote:
    > I am interested to know if the pointer value for the memory address can
    > be changed by a compiler if the constness of the corresponding type is
    > cast away.


    Not in C (I don't know about C++). Section 6.3.2.1
    paragraph 2: "If the lvalue has qualified type, the value has
    the unqualified version of the type of the lvalue; [...]" Thus,
    the value of a const-qualified pointer to some object is equal to
    the value of an unqualified pointer to the same object. It's
    possible that the representation could be different (do not
    mis-read 6.2.5/25 as prohibiting this), but `==' must hold.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jul 9, 2005
    #2
    1. Advertising

  3. Me Guest

    wrote:
    > I am interested to know if the pointer value for the memory address can
    > be changed by a compiler if the constness of the corresponding type is
    > cast away.


    The bits may change, but it's value can't. i.e. you can use the
    equality/relational operators to compare it, but you can't use memcpy.
    You can however use memmove/memcpy to copy the bits over though.

    > inline char* deconstify1(char const * X) { return (char*) X; }
    > inline char* deconstify2(char const * X) { return const_cast<char*>(X);
    > }


    These two mean the exact same thing.

    > const char source [] = "Test";
    > char* alias1 = deconstify1(source);
    > char* alias2 = deconstify2(source);
    >
    > if ((source != alias1) || (source != alias2) || (alias1 != alias2))
    > { printf("unequal: %p %p %p", source, alias1, alias2); }


    I think you meant && and not ||. Even with &&, this example will always
    evaluate to true. Your example doesn't even answer what you really
    mean. What you really meant was:

    const char source [] = "Test";
    const char *p1 = source;
    char *p2 = deconstify1(source);
    const char *p3;

    memcpy(&p3, &p2, sizeof(p2));

    p1 == p3

    And the answer is: yes, this is guaranteed to be true because
    qualifiers only change the level of access in terms of the type system,
    not the way the bits are interpreted in a pointer:

    3.9.2/3 Pointers to cv-qualified and cv-unqualified versions (3.9.3) of
    layout-compatible types shall have the same value representation and
    alignment requirements (3.9).

    ^-- this is an even stronger guarantee about the representation being
    the same

    3.9.3/1 The cv-qualified or cv-unqualified versions of a type are
    distinct types; however, they shall have the same representation and
    alignment requirements (3.9).50)
    3.9.3/1#50) The same representation and alignment requirements are
    meant to imply interchangeability as arguments to functions, return
    values from functions, and members of unions.

    ^-- this is extra to say that even the top level const on pointers have
    the same representation, so we can change "const char *p1" to "const
    char * const p1" and it will still work.


    > Can this happen on a current platform?
    > Does any tool try to copy the data to a read-only area to achieve any
    > protection?


    I don't understand what you're asking. Any const object[*] is allowed
    to be stored in read only memory. You can cast away constness and read
    from it, but any write to that storage location results in undefined
    behavior.

    [*] top level consts, i.e. "int * const var" is allowed to be stored in
    read only memory but "const int *var" is not.
     
    Me, Jul 9, 2005
    #3
  4. Me Guest

    Me wrote:
    > wrote:
    > > I am interested to know if the pointer value for the memory address can
    > > be changed by a compiler if the constness of the corresponding type is
    > > cast away.

    >
    > The bits may change, but it's value can't. i.e. you can use the
    > equality/relational operators to compare it, but you can't use memcpy.


    I meant memcmp.
     
    Me, Jul 9, 2005
    #4
  5. Guest

    > No. The result of a const_cast on a pointer must refer
    > to the same object as the original pointer.
    > Note that the result of writing to an object that was
    > initially declared const is undefined.


    How do you think about the following code example?

    struct context
    {
    long key;
    char const * name;
    } ctx;

    if (ctx.name = (char*) strdup(source))
    {
    // The string is treated as a constant after the initial assignment.
    ctx.key = rand();
    printf("%li: %s", ctx.key, ctx.name);

    // Release memory after processing
    free(deconstify1(ctx.name));
    }

    Regards,
    Markus
     
    , Jul 9, 2005
    #5
  6. Guest

    [...]
    > Thus, the value of a const-qualified pointer to some object is
    > equal to the value of an unqualified pointer to the same object.
    > It's possible that the representation could be different
    > (do not mis-read 6.2.5/25 as prohibiting this), but '=='
    > must hold.


    How can a representation be different and manage the same object here?
    What is the difference that can be recognized by the relational
    operators or the function "memcmp"?

    Regards,
    Markus
     
    , Jul 9, 2005
    #6
  7. Eric Sosman Guest

    wrote:
    > [...]
    >
    >>Thus, the value of a const-qualified pointer to some object is
    >>equal to the value of an unqualified pointer to the same object.
    >>It's possible that the representation could be different
    >>(do not mis-read 6.2.5/25 as prohibiting this), but '=='
    >>must hold.

    >
    >
    > How can a representation be different and manage the same object here?
    > What is the difference that can be recognized by the relational
    > operators or the function "memcmp"?


    It is possible for different representations of a type
    to correspond to the same value as determined by `=='. The
    floating-point types offer a familiar example, since there
    are two different representations of the value zero; there
    may also be different "unnormalized" representations of some
    numbers. Identical representations usually imply equality
    (an exception is NaN), but equality does not imply identical
    representation.

    As for pointers -- well, a certain widely-used architecture
    supports a "segment plus offset" addressing scheme that can
    address the same location with many segment/offset pairs. Or
    imagine a system with (say) 48-bit addresses in 64-bit pointers;
    the 16 extra bits might not participate in pointer comparisons
    at all. They might even carry flags for attributes like `const'
    or "obtained from malloc()" or the like, which could be useful
    for debugging and validation even if they didn't contribute to
    the pointer's value.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jul 9, 2005
    #7
  8. writes:
    >> No. The result of a const_cast on a pointer must refer
    >> to the same object as the original pointer.
    >> Note that the result of writing to an object that was
    >> initially declared const is undefined.

    >
    > How do you think about the following code example?
    >
    > struct context
    > {
    > long key;
    > char const * name;
    > } ctx;
    >
    > if (ctx.name = (char*) strdup(source))
    > {
    > // The string is treated as a constant after the initial assignment.
    > ctx.key = rand();
    > printf("%li: %s", ctx.key, ctx.name);
    >
    > // Release memory after processing
    > free(deconstify1(ctx.name));
    > }


    strdup() is not a standard function. Assuming you're referring to the
    commonly implemented function of that name, the cast is unnecessary
    and potentially dangerous.

    You don't show us an implementation of the deconstify1() function. (I
    think it was in a previous article, but I'm too lazy to go looking for
    it.)

    It's generally not a good idea to use // comments in code posted to
    comp.lang.c. C99 does support them, but line wrapping can cause
    problems. And cross-posting to comp.lang.c and comp.lang.c++ is
    almost never a good idea; they're two distinct langauges with just
    enough similarities to cause arguments.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jul 9, 2005
    #8
  9. Guest

    [...]
    > As for pointers -- well, a certain widely-used architecture
    > supports a "segment plus offset" addressing scheme that can
    > address the same location with many segment/offset pairs. Or
    > imagine a system with (say) 48-bit addresses in 64-bit pointers;
    > the 16 extra bits might not participate in pointer comparisons
    > at all. They might even carry flags for attributes like `const'
    > or "obtained from malloc()" or the like, which could be useful
    > for debugging and validation even if they didn't contribute to
    > the pointer's value.


    Thanks for this clear explanation.
    It reminds to think about the memory layout for the compiler's internal
    pointer data structure.

    Are any improvements for the memory API in development to add the
    capability to manipulate such flags?
    Would it fit to a variant of the "realloc" programming interface to
    change properties like "readable", "writeable" or "executeable"?
    http://en.wikipedia.org/wiki/NX_bit

    Regards,
    Markus
     
    , Jul 9, 2005
    #9
  10. Guest

    > You don't show us an implementation of the deconstify1() function.
    > (I think it was in a previous article, but I'm too lazy to go
    > looking for it.)


    How do you think about this code example?

    struct context
    {
    long key;
    char const * name1;
    string const * name2;
    } ctx;

    char* X = (char*) malloc(5);

    if (X)
    {
    strcpy(X, "Test");
    ctx.name1 = X;
    ctx.name2 = new string("check");

    /* Treat it as a constant after the initial assignment */
    if (ctx.name2)
    {
    ctx.key = rand();
    printf("%li: %s", ctx.key, ctx.name1);
    cout << *ctx.name2;

    {
    string* alias1 = const_cast<string*>(ctx.name2);

    if (memcmp(ctx.name2, alias1, sizeof(alias1)))
    {
    printf("1. changed representation: %p %p", ctx.name2, alias1);
    }

    delete alias1;
    }
    }

    /* Release memory after processing */
    {
    char* alias2 = (char*) ctx.name1;

    if (memcmp(ctx.name1, alias2, sizeof(alias2)))
    {
    printf("2. changed representation: %p %p", ctx.name1, alias2);
    }

    free(alias2);
    }
    }


    > It's generally not a good idea to use // comments in code posted to
    > comp.lang.c. C99 does support them, but line wrapping can cause
    > problems. And cross-posting to comp.lang.c and comp.lang.c++ is
    > almost never a good idea; they're two distinct langauges with just
    > enough similarities to cause arguments.


    Well, I try to discuss some details for common sense.

    Regards,
    Markus
     
    , Jul 10, 2005
    #10
  11. wrote:

    > How do you think about this code example?


    *What* I think about your C++ code example is that it ought not be
    posted to comp.lang.c. Please pay attention to what you are doing.
    Follow-ups set.
     
    Martin Ambuhl, Jul 10, 2005
    #11
  12. CBFalconer Guest

    wrote:
    >
    > > You don't show us an implementation of the deconstify1() function.
    > > (I think it was in a previous article, but I'm too lazy to go
    > > looking for it.)

    >
    > How do you think about this code example?


    Very little.

    >
    > struct context
    > {
    > long key;
    > char const * name1;
    > string const * name2;


    You haven't defined 'string'.

    > } ctx;
    >
    > char* X = (char*) malloc(5);


    You should NEVER cast the return from malloc. Where did the magic
    number '5' come from?

    >
    > if (X)
    > {
    > strcpy(X, "Test");
    > ctx.name1 = X;
    > ctx.name2 = new string("check");


    'new' is a syntax error. This is c.l.c, not c.l.c++.
    >
    > /* Treat it as a constant after the initial assignment */
    > if (ctx.name2)
    > {
    > ctx.key = rand();
    > printf("%li: %s", ctx.key, ctx.name1);
    > cout << *ctx.name2;


    You haven't defined cout. Why do you want to left shift it?
    *ctx.name2 is not a suitable argument anyhow.

    >
    > {
    > string* alias1 = const_cast<string*>(ctx.name2);


    More syntax errors. Again, this is c.l.c.

    .... snip remainder. F'ups set. c.l.c / c.l.c++ crossposts are
    pure foolishness.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
     
    CBFalconer, Jul 10, 2005
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. avnrao
    Replies:
    1
    Views:
    7,334
    avnrao
    May 4, 2004
  2. Patrice
    Replies:
    0
    Views:
    923
    Patrice
    May 4, 2004
  3. Raterus
    Replies:
    0
    Views:
    463
    Raterus
    Jun 2, 2004
  4. Alex Stevens
    Replies:
    0
    Views:
    805
    Alex Stevens
    Aug 10, 2004
  5. Replies:
    12
    Views:
    508
    CBFalconer
    Jul 10, 2005
Loading...

Share This Page