Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NULL passed directly to a function expecting a const reference parameter (VC++ 4.2)

I am looking at something that I discovered in an old code base, and I am pretty confused.

Here is a function definition:

void vUpdateSequenceDetailsAndIncrement(
            const CallEvent& roCPEvent,
            const CallInfo& roCallInfo,
            BOOL bCreationEvent);

Here it is being called:

vUpdateSequenceDetailsAndIncrement(roCPEvent, NULL, FALSE);

Here NULL is being passed directly to the reference parameter roCallInfo. This function eventually calls:

vTimeChange(*pSeqDetails, roCPEvent, roCallInfo);

which is defined:

void vTimeChange(const SequenceDetails& roSequenceDetails,
        const CallEvent& roCPEvent,
        const CallInfo& roCallInfo)

Again passing the possibly NULL value to roCallInfo. I thought that NULL could not be passed as a reference? Does anyone know if VC++ 4.x had some kind of problem which made this kind of code okay? If NULL can be passed as a reference then what happens when in vTimeChange something like this happens:

roCallInfo.getCallStartTime(); 

Is that not a dereference of NULL in the same way as if I were to do

CallInfo * info = NULL;
info->getCallStartTime();

? I'll probably put a guard in there anyways and let the compiler remove it if unnecessary, but I'd love to get to the bottom of how this is happening!

Thanks.

like image 340
Dennis Avatar asked Dec 12 '22 09:12

Dennis


2 Answers

Depends on how NULL is defined in VC 4.2

If it is just

#define NULL 0 

then you are actually getting this under the hood:

vUpdateSequenceDetailsAndIncrement(roCPEvent, CallInfo(0), FALSE);

and reference of temp var of type CallInfo is passed to the function (if CallInfo has compatible ctor)

like image 186
c-smile Avatar answered Dec 14 '22 22:12

c-smile


I thought that NULL could not be passed as a reference?

A valid reference can't be null, but an invalid one can be null.
What you have here is an Invalid Reference.

The fact that a reference can't be null does not mean that references are somehow safer than pointers, as you see here in this case. There can be many ways in which an program may lead to Invalid References, Your code is one such example.

Reference Wikipedia:
There are also de facto ways that a reference can start out invalid. Because a reference is usually implemented as an underlying pointer, initializing a reference on a pointer-dereferencing expression, will usually be implemented by the compiler as a simple assignment from the pointer to the underlying pointer of the reference. Thus, if you have a NULL pointer or a pointer pointing to an invalid location in memory, you will de facto have a reference that points to NULL or an invalid location. C++ purists would argue that, technically, dereferencing a NULL or invalid pointer leads to undefined behavior anyway, so this does not violate the assertions above that a reference cannot be null or point to arbitrary places in memory. However, this ignores the fact that in this case, the underlying implementation simply performs an "assignment", and there is no access of the memory location involved, so this initialization of the reference usually does not cause problems, and programmers must be aware of the possibility of a de facto "invalid" reference in a real program.

Using the Invalid Reference roSequenceDetails would eventually lead to an Undefined Behavior.

like image 35
Alok Save Avatar answered Dec 14 '22 22:12

Alok Save