LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Compiler bug with NULL pointers

Hi I am witing a implementing a com interface in labwindows as below.

To get to the implementing object from the interface I am using the following macro

#define IMPL(class, member, pointer) \
    (&((class *)0)->member == pointer, ((class *) (((long) pointer) - offsetof(class, member))))

This technique is used though com with ansi c as far as I can tell.

This code works in vc++ and gcc but in lab windows I get dereference of NULL pointer exceptions.

Is this a bug in the compiler ?

A test case is below.
Thanks for the help.

Glenn


#include <objbase.h>       

// from stddef.h
#ifndef offsetof
#define offsetof(s,m)  (size_t)&(((s *)0)->m)
#endif

#define IMPL(class, member, pointer) \
    (&((class *)0)->member == pointer, ((class *) (((long) pointer) - offsetof(class, member))))


typedef struct
{
    IUnknown ifoo;
  
} CUnknown;

int main()
{
    CUnknown *cUnknown = (CUnknown*) malloc(sizeof(CUnknown));
   
    IUnknown *ptr = &(cUnknown->ifoo);

    CUnknown *cUnknown2 = IMPL(CUnknown, ifoo, ptr);
   
    return 0;
}

0 Kudos
Message 1 of 4
(3,901 Views)

The problem you are seeing is that the CVI user protection is detecting a NULL dereference (which is correct, as far as is goes). This should only happen in debug mode, release mode should work just fine.

To work around this, you could modify your macro to disable protection errors around this code, similar to the following:

#if _CVI_DEBUG_
#define IMPL_HELPER(class, member, pointer) \
    (&((class *)0)->member == pointer, ((class *) (((long) pointer) - offsetof(class, member))))
#define GET_IMPL(class, member, pointer, impl) \
 do { \
  int state = SetBreakOnProtectionErrors(0); \
  impl = IMPL_HELPER(class, member, pointer); \
  SetBreakOnProtectionErrors(state); \
 } while (0)
#else
#define GET_IMPL(class, member, pointer, impl) \
    (impl = (&((class *)0)->member == pointer, ((class *) (((long) pointer) - offsetof(class, member)))))
#endif

This doesn't allow the more straightforward usage, but works. You could probably work some more macro magic and get the nice usage back, depending on how much code you have that depends on it.

To see how we "work around" this in our libraries, you can compare CVI's definition of offsetof() to the one in included in your code; it is defined in cvixx\include\ansi\stddef.h:

#define offsetof(t, mem) ((size_t) ((char *)&(((t *)8)->mem) - (char *)8))

Hope this helps,

-alex

Message 2 of 4
(3,890 Views)
Glenn,
 
Well, I had a response but it looks like the one up top is better, so I'll just take mine away 🙂

Message Edited by DaveC on 03-15-2006 11:09 AM

0 Kudos
Message 3 of 4
(3,891 Views)
In my original post, I was trying to make the reason for the error clear.
 
An alternative solution (which is simpler) would be to:
 
1. Use CVI's offsetof by including our header instead of defining it yourself; and
 
2. Change the address in your IMPL macro to make the address non-NULL:
 
#define IMPL(class, member, pointer) \
    (&((class *)8)->member == pointer, ((class *) (((long) pointer) - offsetof(class, member))))
 
This is functionally equivalent, and should not throw any errors.
 
Hope this helps,
 
-alex
Message 4 of 4
(3,880 Views)