Strange GetLastError return in Managed C++

1k views Asked by At

I have a really strange problem with GetLastError and managed C++. GetLastError is returning something very strange after transitioning from unmanaged code to managed code.

The error code: 122 - The data area passed to a system call is too small.

Additionally, the passed in strMessage is making it to the server.

Unmanaged function:

   DWORD SendMessage(LPCTSTR strMessage, CString * strResponse)
   {

     DWORD dwLastError;
     BOOL bSuccess = FALSE;
     try 
     {
          //some socket code
          int ret =  recv...
          if (ret == SOCKET_ERROR || ret == 0)
          {
                Log(GetLastError());  //falls into here
                Log(WSAGetLastError());
                throw "Failed!"
          }
          bSuccess = TRUE;
     }
     catch (LPCTSTR pszException)
     {
         dwLastError = GetLastError();
         Log(pszException);
         Log(dwLastError );
         Log(WSAGetLastError());
     }

     Log(dwLastError);
     SetLastError(dwLastError);
     return bSuccess;
   }

Managed Code:

  void SendManagedMessage(String ^ strMessage)
  {
    CString cstrMessage = (char*) Marshal::StringToHGlobalAnsi(strMessage).ToPointer();
    CString cstrResponse;
       if (!SendMessage(cstrMessage, &cstrResponse))
       {
           Log("Failed to send managed message");
           Log(GetLastError());
       }

       //...
  }

Log output

0
0
Failed!
Failed!
0
0
0
Failed to send managed message
122
2

There are 2 answers

2
asveikau On BEST ANSWER

Many functions will call SetLastError as a side-effect while doing their work. Typically this means that a function calls some other function, which might have some internal failure for which it might call SetLastError, and so the previous error value is overwritten.

As an example, it's quite likely that something called by the Log function calls something that sets the ERROR_INSUFFICIENT_BUFFER, handles that error, and returns success. Result? Even though your code didn't fail in a larger sense, your error value is clobbered.

When Win32 functions fail, you need to take some care to call GetLastError before calling too much unrelated code.

Update: I would also read the link in the comment. Also, reading your code, where it says "Failed" followed by 0 error codes, I think likely what is happening is the other end closed the socket (i.e. recv returned 0).

0
Jim Rhodes On

You may want to try adding:

dwLastError = 0;

For the success case. The way you have it, you can be calling SetLastError with an uninitialized variable. I am surprised you are not getting a compiler warning.