Re: man malloc

From: Giorgos Keramidas (keramida_at_ceid.upatras.gr)
Date: 08/19/05

  • Next message: Randy Pratt: "Re: 5.4 or 6 ?"
    Date: Fri, 19 Aug 2005 14:43:17 +0300
    To: Dmitry Mityugov <dmitry.mityugov@gmail.com>
    
    

    On 2005-08-19 15:00, Dmitry Mityugov <dmitry.mityugov@gmail.com> wrote:
    >On 8/19/05, Giorgos Keramidas <keramida@ceid.upatras.gr> wrote:
    >>On 2005-08-18 22:17, Dmitry Mityugov <dmitry.mityugov@gmail.com> wrote:
    >>>On 8/18/05, Giorgos Keramidas <keramida@ceid.upatras.gr> wrote:
    >>>> It may be surprising, but casting back and forth *MAY* change the
    >>>> value of the pointer.
    >>>> ...
    >>>
    >>> Could you back up this assertion with an example, please?
    >>
    >> Do I really have to?
    >> ...
    >
    > I just wanted to learn something new. Please, post an example if you can.

    There is an easy to reproduce case, when running executables of certain
    "memory models" in MS-DOS. Many users forget that function pointers are
    *NOT* the same as object pointers. They generally happen to "just work"
    on most UNIX machines, but they are not the same at all.

    For instance, this will tend to work on FreeBSD:

         1 #include <assert.h>
         2 #include <stdio.h>
         3 #include <stdlib.h>
         4
         5 static int increase(int *);
         6 static int decrease(int *);
         7
         8 typedef int (*fptr_t)(int *);
         9
        10 int
        11 main(void)
        12 {
        13 int k, oval, val;
        14 char *p[] = { (char *)increase, (char *)decrease, };
        15 fptr_t fptr;
        16
        17 val = 0;
        18 for (k = 0; k < 10; k++) {
        19 fptr = (fptr_t)(p[rand() % 2]);
        20 oval = fptr(&val);
        21 printf("%3d -> %3d\n", oval, val);
        22 }
        23 return (0);
        24 }
        25
        26 int
        27 increase(int *xp)
        28 {
        29 int old;
        30
        31 assert(xp != NULL);
        32 old = *xp;
        33 *xp += 1;
        34 return (old);
        35 }
        36
        37 int
        38 decrease(int *xp)
        39 {
        40 int old;
        41
        42 assert(xp != NULL);
        43 old = *xp;
        44 *xp -= 1;
        45 return (old);
        46 }

    On most UNIX installations I've seen, the (char *) pointers at line 14
    can save the address of a function, even though this is not allowed by
    the C standard. If you build this with GCC using the -std=c89 -pedantic
    options, a warning *IS* printed both for the dubious casts of function
    pointers to (char *) in line 14 and for the cast back to a function
    pointer (simplified a bit through a typedef) at line 19:

    % foo.c: In function `main':
    % foo.c:14: warning: ISO C forbids conversion of function pointer to object pointer type
    % foo.c:14: warning: ISO C forbids conversion of function pointer to object pointer type
    % foo.c:19: warning: ISO C forbids conversion of object pointer to function pointer type

    Having said that this is *NOT* standard C, now I can tell you why this may
    bite you in bad ways on some environments, even though it just happens to work
    on FreeBSD, Linux and Solaris, if you build the program without all the
    warnings of -std=c89.

    When programming with certain "memory models" in DOS though, you may find that
    a pointer to a function requires 32 bits of storage, while a pointer to the
    data area of the program requires only 16 (because, for instance, the program
    has a very large code area but it has only one 65 KB segment for storing data).

    In that case, a function pointer that is "coerced" into a (char *) may
    end up being trimmed. When you "coerce" it back to a function pointer
    it will almost certainly point to the wrong place. That's not very good.

    - Giorgos

    _______________________________________________
    freebsd-questions@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-questions
    To unsubscribe, send any mail to "freebsd-questions-unsubscribe@freebsd.org"


  • Next message: Randy Pratt: "Re: 5.4 or 6 ?"

    Relevant Pages

    • Re: Passing execution to a memory address
      ... forbidden initialization of function pointer with void pointer ... int add1 ...
      (comp.lang.c)
    • Re: function * = void *
      ... It doesn't have to be the *correct* kind of function pointer: ... It's prototyped to return a void *. ... The ISO C standard does not require that pointers to functions can be ...
      (comp.lang.c)
    • Re: Some pointer quiestions again
      ... A function pointer can be converted to a void pointer but ... You can do the conversion with a cast: ... >void pointer reliably, if not then there would appear to be no portable ...
      (comp.lang.c)
    • Re: function * = void *
      ... a.c:14: warning: ISO C forbids conversion of object pointer to function ... There is no guarantee that a function pointer can FIT in a void * ... It wouldn't surprise me if there will be new platforms where there ...
      (comp.lang.c)
    • Re: Function Pointers and NULL/0
      ... > PrioFunPreferGroundGoals, ... > function pointer type. ... My suspicion is that that causes the warning. ... > function pointer equivalent of NULL, i.e. a pointer that is considered ...
      (comp.lang.c)