From: SourceForge.net <no...@so...> - 2004-02-22 22:09:33
|
Bugs item #902322, was opened at 2004-02-22 23:00 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=102435&aid=902322&group_id=2435 Category: None Group: None Status: Open Resolution: None Priority: 5 Submitted By: Dimitry Andric (dimitryandric) Assigned to: Nobody/Anonymous (nobody) Summary: Inline putc returns EOF for char 0xFF (with optimization) Initial Comment: OS version: Windows XP US, SP1 gcc version: gcc version 3.3.1 (cygming special) ld version: GNU ld version 2.14.90 20030901 mingw version: 3.2 (according to _mingw.h) build environment: Cygwin (as of 2004-02-22) When I was building GNU GMP 4.1.2 using MinGW32 under Cygwin, I ran into a weird problem during the "make check" phase. During its checks, it asserts in gmp-4.1.2/tests/mpz/t-io_raw.c, on the following piece of code (surrounding parts are irrelevant): fp = fopen_wplusb_or_die (FILENAME); for (j = 3; j >= 0; j--) ASSERT_ALWAYS (putc ((size >> (j*8)) & 0xFF, fp) != EOF); It turns out this assertion triggers when the input char to putc() is 0xFF, and if the program is built with any optimization. The version of putc() used in this case is inline, and defined in stdio.h as: __CRT_INLINE int __cdecl putc (int __c, FILE* __F) { return (--__F->_cnt >= 0) ? (int)(*__F->_ptr++ = (char)__c) : _flsbuf (__c, __F); } Now, in the case that __F->_cnt >= 0, the input _integer_ 0xFF is first case to a (signed) char, resulting in a char with value -1. That is okay in itself, and the char is stored into the output buffer __F->_ptr. However, for the return value, this result is cast to int again, giving an int with value -1, which is alas equal to EOF! So in this particular case, the putc seems to fail, while it has not (if _flsbuf is not called, there actually is no way it could fail). Also, the return value should have been an integer with a positive value 0xFF, not -1. Here is a very simple program, t-putc.c, to exhibit this behaviour: #include <stdio.h> int main(void) { if (putc(0xFF, stdout) == EOF) { fputs("first putc fails\n", stderr); return 1; } else if (putc(0xFF, stdout) == EOF) { fputs("second putc fails\n", stderr); return 2; } else { fputs("both putc's succeeded\n", stderr); return 0; } } If you compile this with any optimization, i.e: gcc -mno-cywin -Wall -W -O t-putc.c -o t-putc and then run it, redirecting output to a file (needed because only then buffering will take place): ./t-putc > foo you will get the message "second putc fails". The first putc calls _flsbuf() to create the initial output buffer, and the second one returns an incorrect EOF! If you compile this with no optimization, the putc _function_ equivalents from msvcrt.dll will be called instead, so in that case they will both succeed. To fix this problem, I've attached a patch for stdio.h, which simply ANDs the result value with 0xFF before returning it. The same method is used for the getc, getchar and putchar inline functions, which have analogous problems. I know this error seems rather obscure, so please feel free to contact me anytime if something is unclear about it. :-) Cheers, Dimitry ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=102435&aid=902322&group_id=2435 |