Thread: restrict and function pointers

  1. #1
    Registered User
    Join Date
    Jun 2004
    Posts
    201

    restrict and function pointers

    Do function pointers suffer from the same aliasing problems as normal pointers?

    I mean, suppose you use qsort and pass it a function pointer, will it get reloaded again whenever the function is used?

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    What do you mean "reloaded"? Will what get "reloaded"?

    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Jun 2004
    Posts
    201
    first a standard "restrict" example:

    you have a function with two pointer parameters
    void Func(int *a, int *b, int n)
    {
    for ( int i = 0; i < n; i++)
    {
    *a += *b;
    a++;
    }
    }

    because b might be an alias to some address within a b gets reloaded every time in the loop. That's why restrict is introduced.

    But you probably knew that already so now on to the function pointer example:

    int MyCompare(const void *pv1, const void *pv2) { ... }

    void Func(int (*func)(const void*, const void*))
    {
    for (...)
    (*func)(x, y);
    }

    Can the compiler assume that the value of the function pointer "func" won't change or will the value be reloaded every time the function pointer is dereferenced?

    I hope I'm clear

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well a pointer is a pointer. As such, you can have an array of function pointers, and "walk" down the array, calling function after function...

    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Obsessed with C chrismiceli's Avatar
    Join Date
    Jan 2003
    Posts
    501
    I have never heard of pointers being reloaded. I am pretty sure that they are not. If you would want to make sure that they are not changed, use some protection on it, like a semaphore. Where did you get information that pointers are reloaded in case they change. Pointers just store a number, so if that number were to change it wouldn't matter because the dereference looks at that number, there is no need to reload.
    Help populate a c/c++ help irc channel
    server: irc://irc.efnet.net
    channel: #c

  6. #6
    .
    Join Date
    Nov 2003
    Posts
    307
    I do not know what the original poster is asking, either.
    I think he may be confused.

    There is a restrict type qualifier for C99, it's use is limited to pointers. For example, you will see it in the memcpy() prototype:

    Code:
     
    void *memcpy(void *restrict str1, const void * restrict str2, size_t size);
    By qualifying str1 and str2 with restrict, the prototype asserts that the two arguments point to non-overlapping objects, as I understand it.

    I haven't seen anything about reloading pointers anywhere, not in discussions of restrict in any of the stuff I have. Always interested to see if there's something I missed.

  7. #7
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    What I think he is saying is that:
    Code:
    void Func(int *a, int *b, int n)
    {
        for ( int i = 0; i < n; i++)
        {
            *a += *b;
            a++;
        }
    }
    can't safely be optimised [edit]by the compiler[/edit] to the potentially faster:
    Code:
    void Func(int *a, int *b, int n)
    {
        register int temp = *b;
    
        for ( int i = 0; i < n; i++)
        {
            *a += temp;
            a++;
        }
    }
    because int* b may point to a location in the array pointed to by int* a. Therefore, b must be reloaded at every use. Assumably, the restrict keyword allows this optimization by telling the compiler that int* b and int* a can not overlap.

    What I think he could be asking, is does the same thing apply with function pointers. That is, can this:
    Code:
    void Func(int (*func)(const void*, const void*))
    {
        for (...)
            (*func)(x, y);
    }
    be optimised with something like this pseudo-code:
    Code:
    void Func(int (*func)(const void*, const void*))
    {
       processorCachePtr temp = CopyFuncFromSlowRam(func);
    
       for (...)
          (*temp)(x, y);
    }
    or does func need to be run from its original location each time in case the code is changed through another pointer.

    This is all totally processor/OS/implementation/optimisation level/code specific.

    >> Can the compiler assume that the value of the function pointer "func" won't change or will the value be reloaded every time the function pointer is dereferenced? <<

    Yes, it can assume the value of func won't change in this case. If func equals 0x3212 on entry, it will stay with that value. What it may not always be able to assume is that the code that func points to will remain constant. However, this is something that could potentially be determined at compile time:
    Code:
    my_function(const void*, const void*);
    Func(my_function);
    In this case the compiler could possibly determine that the code for my_function can not change.
    Code:
    FUNC_PTR my_function = VirtualAlloc(NULL, 200, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    Func(my_function);
    In this case the compiler could possibly determine that the code for my_function can change.

    If this post has confused you, don't worry, it has confused me more.
    Last edited by anonytmouse; 06-25-2004 at 08:58 PM.

  8. #8
    Registered User linuxdude's Avatar
    Join Date
    Mar 2003
    Location
    Louisiana
    Posts
    926
    I know that you can't use the &(address of) operator on registers. So code with pointers defined as registers would be dangerous.
    Last edited by linuxdude; 06-25-2004 at 08:46 PM.

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    The register keyword doesn't even ensure that the variable is put in a register. It's basicly a worthless keyword now days, because your compiler optimizes as it sees fit. IIRC, you cannot force it to be a register. It's just a suggestion.

    However, as long as you don't need the address of a pointer, I suppose it could work in a register. You wouldn't want to try to assign the address of say your loop counter to a pointer though, had you attempted to make that a register.

    But really, there isn't much need for register any more.

    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by Laserve
    Do function pointers suffer from the same aliasing problems as normal pointers?
    I mean, suppose you use qsort and pass it a function pointer, will it get reloaded again whenever the function is used?
    A function pointer is always loaded each and every time. Actual functions entry points, on the other hand, are traditionally constant, read-only memory locations and thus intrinsically alais-proof, (VirtualAlloc() is an indeed an exception, but then notice it's absence from XP too!).
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  11. #11
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    >> (VirtualAlloc() is an indeed an exception, but then notice it's absence from XP too!). <<
    ?? Reports of VirtualAlloc()'s death seem to have been greatly exaggerated.

    Currently, you can manipulate code in malloc() memory or even on the stack. However, in the future code will have to run from memory specifically marked with the EXECUTE permission(so as to lessen problems with buffer overruns), hence the use of VirtualAlloc() in my sample.

  12. #12
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Hmm, I seem to have read that they were removing it from all future API's - maybe was wrong. Seems a little foolish though to continue supporting it, and if they do that's their own damn fault!
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  13. #13
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    >> Seems a little foolish though to continue supporting it, and if they do that's their own damn fault! <<

    I assume you mean the ability to manipulate code at run-time rather than VirtualAlloc() itself which being the core user mode memory allocation function(along with the Ex version), has many other essential uses. Why do you think run-time code generation should not be allowed? What about run-time code generation by the .net or Java run times? What about thunking?

    http://msdn.microsoft.com/security/p.../exec_imp.aspx

  14. #14
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> ...rather than VirtualAlloc() itself which being the core user mode memory allocation function...

    Sorry, I was confusing the function with VirtualProtect().

    >> Why do you think run-time code generation should not be allowed?

    There is always some level of vunerability exposed with these sort of facilities - when you're trying to secure a system for instance, that can become a real concern.

    >> What about run-time code generation by the .net or Java run times?

    These are closely scrutinized frameworks that (supposedly) implement tightly-controled mechanisms for code generation.

    >> What about thunking?

    The ability to implement system-wide execution analysis and redirection is of course extremely useful, it too has it's vunerabilities as well.

    I don't mean to imply that there is something inherently wrong about having access to those kinds of services - just that they introduce a level of insecurity that can't be ignored either.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. moving median function
    By supermeew in forum C Programming
    Replies: 0
    Last Post: 05-04-2006, 02:37 PM
  2. restrictions on pointers using const
    By Chaplin27 in forum C++ Programming
    Replies: 2
    Last Post: 01-25-2005, 10:23 AM
  3. function pointer
    By linuxdude in forum C Programming
    Replies: 7
    Last Post: 07-29-2004, 04:25 PM
  4. %i or %d - where is the difference?
    By Sargnagel in forum C Programming
    Replies: 3
    Last Post: 11-12-2002, 03:21 PM