Compiler Warning C4801

Return by reference is not verifiable: reason

You cannot store a tracking reference into a local variable and then return it verifiably.

A reference can only be verifiably returned when it can be tracked by the verifier from creation to return point and when it is a reference to an element of an array, or a member of a class.

For more information, see Peverify.exe (PEVerify Tool).

A reference must remain on the stack from creation to return in order to be verifiable.

C4801 is always issued as an error. You can turn off this warning with the #pragma warning or /wd; see warning or /w, /Wn, /WX, /Wall, /wln, /wdn, /wen, /won (Warning Level) for more information.

Example

C4801 will be generated if the verifier cannot see the address taken, so it must assume that it might be an unverifiable reference. The following sample generates C4801.

// C4801.cpp
// compile with: /clr:safe /c
int% f(int% p) {
   return p;   // C4801
}

The following sample generates C4801.

// C4801_b.cpp
// compile with: /clr:safe /c

int% f(int i, array<int>^ ar) {
   int x;
   int% bri = x;   // cannot return a byref to a local.
   if (i < ar->Length) {
      bri = ar[i];   // this byref is ok.
   }

   return bri;   // C4801 not returned within the basic block
}

C4801 can also occur if you attempt to dereference and return a reference value in a try block. This will result in code that cannot be verified because the stack is cleared at the end of a try block, destroying any return value on the stack. Instead, dereference the reference type and assign it to a variable, to ensure that no exception is thrown. Then, at the end of the function, dereference the reference type again and return it.

The following sample generates C4801.

// C4801_c.cpp
// compile with: /clr:safe
using namespace System;

ref class StackEmptyException : public System::Exception {};
ref class StackFullException : public System::Exception {};

template <typename T>
ref struct Stack {

   Stack() {
      topElem = -1;   // initialize stack
      stackPtr = gcnew array<T>(10);
   }

   void push(const T%);
   T% top();

private:
   int topElem;  
   array<T>^ stackPtr;  
};

template <typename T> 
T% Stack<T>::top() {
   try {
      return stackPtr[topElem];   // C4801
      // Try the following line instead.
      // T% deadstore = stackPtr[topElem] ;
   }

   catch (System::IndexOutOfRangeException ^ e) {
      throw gcnew StackEmptyException();
   }

   catch (System::Exception ^ e) {
      throw;
   }

   return stackPtr[topElem] ;
}

int main() {
   typedef Stack<Int32> IntStack;
   IntStack ^ is = gcnew IntStack();

   int i = 1;
   while (1) {
      try {
         is->push(i++);
      }
      catch (System::Exception ^ e) {
         break;
      }
      Console::Write("{0} ", is->top());
   }
}