Visual C++ 2015 error

Discussion of chess software programming and technical issues.

Moderator: Ras

Robert Pope
Posts: 570
Joined: Sat Mar 25, 2006 8:27 pm
Location: USA
Full name: Robert Pope

Visual C++ 2015 error

Post by Robert Pope »

I upgraded to Windows 10 this weekend, so I decided to upgrade from Visual Studio 2013 to 2015 while I was at it. To my surprise, my chess program doesn't compile anymore. The problem is some generic I/O code I borrowed from the WinBoard forum a long time ago:

Code: Select all

int Bioskey(void) { 
  static int init = 0, pipe; 
  static HANDLE inh; 
  DWORD dw; 
  if (XBoard) { 
    if (!init) { 
      init = 1; 
      inh = GetStdHandle(STD_INPUT_HANDLE); 
      pipe = !GetConsoleMode(inh, &dw); 
      if (!pipe) { 
        SetConsoleMode(inh, dw & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT)); 
        FlushConsoleInputBuffer(inh); 
      } 
    } 
    if (stdin->_cnt > 0) 
      return stdin->_cnt; 
    if (pipe) { 
      if (!PeekNamedPipe(inh, NULL, 0, NULL, &dw, NULL)) return 1; 
        return dw; 
    } 
    else { 
      GetNumberOfConsoleInputEvents(inh, &dw); 
      return dw <= 1 ? 0 : dw; 
    } 
  } 
  else return _kbhit(); 
} 
It chokes on:
if (stdin->_cnt > 0)
return stdin->_cnt;
with Error C2039: '_cnt': is not a member of '_iobuf'
class "_iobuf" has no member "_cnt"

Any ideas? I've been googling, but can't figure out what the issue is, or how to resolve it.
jdart
Posts: 4427
Joined: Fri Mar 10, 2006 5:23 am
Location: http://www.arasanchess.org

Re: Visual C++ 2015 error

Post by jdart »

You are referencing a non-standard variable that you are assuming is part of "stdin". It isn't there anymore in the new Windows version.

This code from Arasan shows how I handle input on Windows:

Code: Select all

 while (!polling_terminated) {
      BOOL bSuccess;
      DWORD dwRead;
      if (_isatty(_fileno(stdin))) {
         // we are reading direct from the console, enable echo & control-char
         // processing
         if (!SetConsoleMode(hStdin, ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT |
                         ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT)) {
            cerr << "SetConsoleMode failed" << endl;
         }
         bSuccess = ReadConsole(hStdin, buf, 1024, &dwRead, NULL);
      }
      else {
         bSuccess = ReadFile(hStdin, buf, 1024, &dwRead, NULL);
         if (! bSuccess || dwRead == 0) {
            if (doTrace) cout << "# read error from input pipe" << endl;
#ifdef UCI_LOG
            ucilog << "read error from input pipe" << endl << (flush);
#endif
            break;
	 }
      }
      processCmdChars(buf,(int)dwRead);
   }
Joost Buijs
Posts: 1680
Joined: Thu Jul 16, 2009 10:47 am
Location: Almere, The Netherlands

Re: Visual C++ 2015 error

Post by Joost Buijs »

This morning I installed VS2015 under Windows 10 and I also have some issues with the IO.

My engine compiles without errors and works fine with Arena, but when I use it with WinBoard/Polyglot the IO just hangs.

Basically I do this:

Code: Select all


void uci::init_io
{
	hStdin = GetStdHandle(STD_INPUT_HANDLE);
	hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
	bPipe = (GetFileType(hStdin) == FILE_TYPE_PIPE);

	if (bPipe) {
		setvbuf(stdin, NULL, _IONBF, 0);
		setvbuf(stdout, NULL, _IONBF, 0);
	}

	fflush(NULL);
}

bool uci::check_io
{
	if (bPipe) { // anonymous pipe
		DWORD dwAvail = 0;
		if (PeekNamedPipe(hStdin, NULL, 0, NULL, &dwAvail, NULL) && dwAvail > 0)
			return true;
		return false;
	}

        // console
        return bool(_kbhit());
}

After this I just read from stdin and write to stdout.

Some time ago I already saw that this code had problems with VS2015 beta and decided to wait for the RTM because I thought it was a flaw of the beta.
The strange thing is that it still works with Arena but that it hangs with WinBoard/Polyglot.

The good thing is that for the first time it looks like the new Microsoft compiler generates somewhat faster code than the Intel compiler does.
I have to check this a little further.
Joost Buijs
Posts: 1680
Joined: Thu Jul 16, 2009 10:47 am
Location: Almere, The Netherlands

Re: Visual C++ 2015 error

Post by Joost Buijs »

Although PeekNamedPipe() indicates that there are characters available the subsequent fgets() just blocks and does not return.

I wonder whether it is a bug in the MSVC++ 14.0 library or something else. With MSVC++ 12.0 there are no problems at all.
And there is the strange phenomenon that it does not happen under Arena.

When I have some time I will dive further into it.
mar
Posts: 2675
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Visual C++ 2015 error

Post by mar »

Robert Pope wrote:The problem is some generic I/O code I borrowed from the WinBoard forum a long time ago
If you ran your engine in a separate thread, you could have one simple polling loop in main (or elsewhere),
no need for nonportable windows-specific magic ang ugly polling within search...
Joost Buijs
Posts: 1680
Joined: Thu Jul 16, 2009 10:47 am
Location: Almere, The Netherlands

Re: Visual C++ 2015 error

Post by Joost Buijs »

mar wrote:
Robert Pope wrote:The problem is some generic I/O code I borrowed from the WinBoard forum a long time ago
If you ran your engine in a separate thread, you could have one simple polling loop in main (or elsewhere),
no need for nonportable windows-specific magic ang ugly polling within search...
Handling the IO in a separate thread is a lot cleaner, I agree. In the next version of my engine I will certainly do it this way.

A lot of code I use is at least 15 years old and I never changed it because it always worked.
Now I'm intrigued by the fact that it suddenly breaks in combination with MSVC++ 14.0 and WinBoard/Polyglot.
Joost Buijs
Posts: 1680
Joined: Thu Jul 16, 2009 10:47 am
Location: Almere, The Netherlands

Re: Visual C++ 2015 error

Post by Joost Buijs »

Disabling buffering on stdio in combination with fgets() seems to be the culprit.
I don't want to spend more time on it, I will stick to MSVC 12 for the time being.
In the future when I have completely rewritten the IO part I will give it another try.
Robert Pope
Posts: 570
Joined: Sat Mar 25, 2006 8:27 pm
Location: USA
Full name: Robert Pope

Re: Visual C++ 2015 error

Post by Robert Pope »

mar wrote:
Robert Pope wrote:The problem is some generic I/O code I borrowed from the WinBoard forum a long time ago
If you ran your engine in a separate thread, you could have one simple polling loop in main (or elsewhere),
no need for nonportable windows-specific magic ang ugly polling within search...
True, but then I'd have to get more competent with threads. Trades one can of worms for another. :)

What's the portable method of threading?
jdart
Posts: 4427
Joined: Fri Mar 10, 2006 5:23 am
Location: http://www.arasanchess.org

Re: Visual C++ 2015 error

Post by jdart »

Generally threading code is not portable. Intel has a threading library that may help though (https://www.threadingbuildingblocks.org/).

C++ 11 has portable threading constructs built into the language. So do some other languages (Go for example). For older C++ there is the Boost library.

(I am using none of these: I have #ifdefs and a couple utility classes that help hide platform dependencies).

--Jon
Robert Pope
Posts: 570
Joined: Sat Mar 25, 2006 8:27 pm
Location: USA
Full name: Robert Pope

Re: Visual C++ 2015 error

Post by Robert Pope »

This is driving me crazy. I compiled and ran the following code on MS Visual Studio Professional 2013 (Windows 8.1):

Code: Select all

#include<stdio.h>
int main(int argc, char* argv[])
{
char buf[256];
    setvbuf(stdin, NULL, _IONBF, 0);
    printf("waiting for input\n");
    fgets(buf, 80, stdin);
    printf("received %s\n", buf);
    printf("exiting:\n");
    fgets(buf, 80, stdin);
return 0;
}
The output is as expected:

waiting for input
A
received A

exiting:
B

But if I compile the exact same code in MS Visual Studio Community 2015 (Windows 10), it keeps waiting for input until I press enter twice:

waiting for input
A
B
C
D


received ABCD


exiting:
E
F
G

If I comment out the setvbuf(), it works as expected, but then I am buffering input.