Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use %zu for printf-style formatting of size_t values. #19339

Merged
merged 1 commit into from Nov 20, 2016

Conversation

mutability
Copy link
Contributor

This is a semi-automated replacement of %d/%i formats with %zu
when the parameter is of type size_t. It was driven by parsing the
warnings generated by PRINTF_CHECKS.

Also fixes one case where a size_t was passed as a width specifier
(this has to be an int)

%zu is specified in C++11 (via C99) so hopefully we are OK with
compatibility there. The alternatives are very ugly (macros embedded
in format strings, or casts everywhere)

This is a semi-automated replacement of %d/%i formats with %zu
when the parameter is of type size_t. It was driven by parsing the
warnings generated by PRINTF_CHECKS.

Also fixes one case where a size_t was passed as a width specifier
(this has to be an int)

%zu is specified in C++11 (via C99) so hopefully we are OK with
compatibility there. The alternatives are very ugly (macros embedded
in format strings, or casts everywhere)
@illi-kun
Copy link
Contributor

According to stackoverflow thread, VS2013 doesn't support %zu. I'm sure this is an issue but I think it's better to state it here.

@mutability
Copy link
Contributor Author

VS2013 also doesn't support C++11, does it? My research seemed to indicate that the more recent visual studio versions that supported C++11, also supported %zu.

@mutability
Copy link
Contributor Author

http://stackoverflow.com/questions/15610053/correct-printf-format-specifier-for-size-t-zu-or-iu suggests that VS2015 does support %zu, VS2013 may or may not it's unclear.

What are we targeting?

(VS2013 apparently doesn't support constexpr either..)

@illi-kun
Copy link
Contributor

Okay, I've checked compiling.md and it seems that we targeted on support of VS2015:

Visual Studio 2015 is required to build Cataclysm.

So you PR is acceptable.

@illi-kun illi-kun self-assigned this Nov 20, 2016
@illi-kun illi-kun merged commit 779a385 into CleverRaven:master Nov 20, 2016
@mutability mutability deleted the printf-sizet branch November 20, 2016 16:45
@Totentag
Copy link

Unintended bugs coming from this.

image

@macrosblackd
Copy link
Contributor

This breaks the Windows release by causing a crash when opening the new inventory UI.

@mutability
Copy link
Contributor Author

What is the Windows release built with?

@DanmakuDan
Copy link
Contributor

MXE cross compiles with MinGW, most likely 4.8.2 from #13652.

@mutability
Copy link
Contributor Author

mutability commented Nov 20, 2016

Looks like we might need -D__USE_MINGW_ANSI_STDIO=1 to tell it to use the standards-conforming *printf not the Microsoft one.

https://stackoverflow.com/questions/25670522/c-program-shows-zu-after-conversion-to-windows

I have no way of testing this.

@DanmakuDan
Copy link
Contributor

Maybe @narc0tiq can check if the flag is applicable to the build. This issue isn't present on MSYS2/mingw gcc 5.2.0.

@illi-kun
Copy link
Contributor

Yeah, I tested these charges with Code::Blocks default compiler in Windows and it woorks fine.

@illi-kun
Copy link
Contributor

It seems that this PR needs to be reverted, sorry for this. Is it ok to just push the 'revert' button or we have some more gentle and safe way to do that?

@codemime
Copy link
Contributor

codemime commented Nov 20, 2016

Shouldn't we revert the PR until the solution is applied? BTW the link that @mutability gave suggests a [quick]fix:

all you need to do to get all of this standard behavior is either #define __USE_MINGW_ANSI_STDIO 1 before any includes if you use any of the printf functions or ...

@codemime
Copy link
Contributor

@illi-kun At the same time.

@codemime
Copy link
Contributor

sorry for this.

That's all right. The side effect wasn't easily predictable.

Is it ok to just push the 'revert' button or we have some more gentle and safe way to do that?

Pushing it creates a reverting pull request. I believe that's perfectly safe.

@mutability
Copy link
Contributor Author

mutability commented Nov 20, 2016

So what's the plan for actually fixing the build issue? I can't test the change I suggested, is there an active developer with the same build environment (same as the CI environment) who can test it?

(if there isn't, that's probably a sign that the CI environment needs to change)

@narc0tiq
Copy link
Contributor

I can theoretically run builds of specific commits right in Jenkins itself, but that'd show up as a new build and would probably get grabbed up by the auto-updater, so let's avoid that.

At the same time, I can also just manually run the same commands in its shell and capture the output. If we're suggesting just that extra #define (as a CXXFLAGS addon), I'll have some binaries for you in a short while.

@narc0tiq
Copy link
Contributor

Okay, here's the wincurses build log and binary taken by checking out this PR (specifically, commit 7dcb672) and adding CXXFLAGS='-D__USE_MINGW_ANSI_STDIO=1' to the build invocation[1].

In my very brief testing, the build is quite unstable; simple things like monsters fighting each other, or eating often (but not always) lead to crashing. This is likely to be the same issue as reported in #19372.


[1] Specifically, the invocation was CXXFLAGS='-D__USE_MINGW_ANSI_STDIO=1' BUILD_NUMBER=pr19339 Platform=Windows Graphics=Curses /www/virt/dev.narc.ro/htdocs/cataclysm/mainline-build.zsh > /www/virt/dev.narc.ro/htdocs/cataclysm/cataclysmdda-pr19339-build.log 2>&1, which should be identical with a Jenkins invocation except for the additional compiler flag.

@mutability
Copy link
Contributor Author

OK, so if that didn't work, then options are (in rough order of my preference):

  1. someone with an environment equivalent to the CI environment (so far that seems to mean @narc0tiq only) does some experimentation and works out how to make it compile with a C++11 compatible printf
  2. update the CI environment to a version that supports C++11 properly (e.g. one of the other Windows build methods above which appears to work OK)
  3. embed our own printf implementation, e.g. https://github.com/fmtlib/fmt, either everywhere or just on Windows builds. NB: this would also fix the existing positional-args problem too I think.
  4. use a macro: ("hey I counted %" PRZU " things", things.size())
  5. forbid use of size_t when formatting: ("hey I counted %d things", (int)things.size())

Doing nothing here is just delaying the inevitable as there are surely platforms where passing a size_t to %d is a crash bug.

@codemime
Copy link
Contributor

The first one appears to be the only viable option.

@mutability
Copy link
Contributor Author

Here's a minimalish test; if you can get that compiling in the CI environment such that it says "vector has 1 elements" when run, then it's probably working.

#include <cstdio>
#include <vector>

int main(int argc, char *argv[])
{
    std::vector<int> v;
    v.push_back(1234);
    printf("vector has %zu elements\n", v.size());
    return 0;
}       

@narc0tiq
Copy link
Contributor

narc0tiq commented Nov 21, 2016

Okay. It just worked. Here's the binary.

My command was ccache /home/narc/mxe/usr/bin/i686-w64-mingw32.static-g++ -ffast-math -Os -Wall -Wextra -fsigned-char -std=c++11 -MMD -c test.cpp -o test.obj && ccache /home/narc/mxe/usr/bin/i686-w64-mingw32.static-g++ -o test.exe test.obj -static (basically, a stripped-down version of the compile commands for the cata binary).

Notably, I left out the -D__USE_MINGW_ANSI_STDIO=1 -- on a previous pass, I had it in, and it also worked.

@mutability
Copy link
Contributor Author

Hm, weird, why is it failing on the full build then..

@mutability
Copy link
Contributor Author

Ok, so it looks like everything goes through vstring_format in output.cpp which has some _MSC_VER-specific magic that invokes _vscprintf_p and _vsprintf_p. I guess that is bypassing the mingw implementation.

The other non-microsoft path uses vsnprintf directly. I wonder if it is simple as dropping the #ifdef _MSC_VER path, can you try turning that ifdef off and using the vsnprintf version?

@mutability
Copy link
Contributor Author

I have no real idea about this, the old MXE produces strange results and the new MXE works fine here.

@narc0tiq
Copy link
Contributor

So I'm working on a new Jenkins and this is funny (but not promising): http://gorgon.narc.ro:8080/job/Cataclysm-Matrix/Graphics=Curses,Platform=Windows_x64/1/console

In file included from /home/narc/src/mxe/usr/lib/gcc/x86_64-w64-mingw32.static/4.9.4/include/c++/map:61:0,
                 from src/json.h:10,
                 from src/enums.h:8,
                 from src/visitable.h:9,
                 from src/character.h:4,
                 from src/player.h:4,
                 from src/bionics.cpp:1:
/home/narc/src/mxe/usr/lib/gcc/x86_64-w64-mingw32.static/4.9.4/include/c++/bits/stl_map.h: In member function 'bool player::activate_bionic(int, bool)':
/home/narc/src/mxe/usr/lib/gcc/x86_64-w64-mingw32.static/4.9.4/include/c++/bits/stl_map.h:212:56: internal compiler error: in expand_expr_addr_expr_1, at expr.c:7672
       { _M_t._M_insert_unique(__l.begin(), __l.end()); }
                                                        ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
Makefile:650: recipe for target 'objwin/bionics.o' failed
make: *** [objwin/bionics.o] Error 1
make: *** Waiting for unfinished jobs....
Build step 'Execute shell' marked build as failure
Recording fingerprints
Finished: FAILURE

Hooray for internal compiler errors.

@mutability
Copy link
Contributor Author

Been a long time now since I saw an ICE..

I did only try a 32-bit build. Let me try a 64-bit build.

@mutability
Copy link
Contributor Author

I get the same ICE with a 64-bit build. Doesn't happen with a 32-bit (i686) build.

@mutability
Copy link
Contributor Author

Actually now that I look at the error, it is a different ICE. Joy.

In file included from /home/oliver/git/mxe/usr/lib/gcc/x86_64-w64-mingw32.static/4.9.4/include/c++/set:61:0,
                 from src/json.h:11,
                 from src/enums.h:8,
                 from src/sounds.h:4,
                 from src/sounds.cpp:1:
/home/oliver/git/mxe/usr/lib/gcc/x86_64-w64-mingw32.static/4.9.4/include/c++/bits/stl_set.h: In function 'void sfx::do_footstep()':
/home/oliver/git/mxe/usr/lib/gcc/x86_64-w64-mingw32.static/4.9.4/include/c++/bits/stl_set.h:225:56: internal compiler error: in expand_expr_addr_expr_1, at expr.c:7672
       { _M_t._M_insert_unique(__l.begin(), __l.end()); }
                                                        ^

@mutability
Copy link
Contributor Author

Getting all sorts of ICEs at different locations depending on the exact compile options (but always in expand_expr_addr_expr_1, at expr.c:7672).

I do notice this in the Makefile:

    # MXE ICE Workaround
    ifeq (${CXXVERSION}, 4.9.3)
      OPTLEVEL = -O3
    else
      OPTLEVEL = -Os
    endif

perhaps that problem persists in 4.9.4

@narc0tiq
Copy link
Contributor

Ah, hey, that could be exactly it! I'll experiment and report back.

@mutability
Copy link
Contributor Author

mutability commented Nov 24, 2016

Yeah, it seems to work OK here if I set -O3. Beware that the current makefile detection stuff is broken (it looks at the output of "gcc" not "$(CROSS)gcc"). I'll put together a patch for that.

@narc0tiq
Copy link
Contributor

I'm getting an odd issue where the x86_64-w64-mingw32.static-g++ is apparently making i386 object files, leading to /home/narc/src/mxe/usr/bin/x86_64-w64-mingw32.static-ld: i386 architecture of input file 'objwin/mod_test.o' is incompatible with i386:x86-64 output. This is really special indeed. Maybe my ccache is ccaching the wrong thing.

@narc0tiq
Copy link
Contributor

No, it's not ccache (it shouldn't have been, so I'm not surprised, but bleh). I need to get back to work; I'll come back to this later.

@patternoia
Copy link
Contributor

As a bit of offtopic: @narc0tiq since you are deploying a new build server (or upgrading existing), could you please install clang/llvm v3.8.1. This will help with linux to mac cross compilation later.

You could very simply install it by cloning osxcross and running CLANG_VERSION=3.8.1 INSTALLPREFIX=/any/path/here ./build_clang.sh. By specifying the INSTALLPREFIX you then ensure you will not damage the current clang installation.
Let me know what you think about this.

@narc0tiq
Copy link
Contributor

narc0tiq commented Nov 24, 2016 via email

@narc0tiq
Copy link
Contributor

So, I found out that make clean doesn't actually clean the tests/objwin. Maybe should fix that sometime.

@narc0tiq
Copy link
Contributor

@patternoia I seem to have v3.8.0 on the new machine (but I haven't plugged in the clang PPA, which may resolve it by way of package (much preferable)). Is the .1 critical?

@patternoia
Copy link
Contributor

Should not be

mutability added a commit to mutability/Cataclysm-DDA that referenced this pull request Nov 27, 2016
This is a semi-automated replacement of %d/%i formats with %zu
when the parameter is of type size_t. It was driven by parsing the
warnings generated by PRINTF_CHECKS.

Also fixes one case where a size_t was passed as a width specifier
(this has to be an int)

Adds a testcase that tests that %zu and positional args work OK.

This requires C++ / C99 printf support. The current CI environment
does not provide this for Windows builds, so this needs to be
merged _after_ the CI environment has been upgraded.

(previously: CleverRaven#19339)
@kevingranade
Copy link
Member

kevingranade commented Nov 30, 2016 via email

@mutability
Copy link
Contributor Author

What invasive workaround do you mean?

Fixing this particular warning is a necessary step towards fixing all the printf warnings, at which point we can turn on enforcement of those warnings in release builds (or as a separate check step) and avoid future bugs involving a mismatch between format strings and arguments.

@narc0tiq
Copy link
Contributor

invasive workaround

I'm not sure it's that invasive, as it's just trading one set of optimizations for another (and it's fairly narrowly targeted at mingw64's x86_64 build target only). We can always narrow it further if someone needs it, but it's more likely mingw64 will update their gcc first... in a couple more years.

@mutability
Copy link
Contributor Author

mutability commented Nov 30, 2016 via email

@narc0tiq
Copy link
Contributor

Yeah, but with #19440 it's targeted on mingw64 entirely -- which it probably needs, at least for now. Eventually, it'll be unnecessary and we can remove it altogether, I hope.

@mutability
Copy link
Contributor Author

Are we building with anything other than gcc 4.9.3 / 4.9.4 for x86_64-w64-mingw32.static? I thought the answer to that was "no"

@mutability
Copy link
Contributor Author

It would be useful if Kevin can clarify what he means too because I don't understand what the issue is - the ICE has nothing to do with this PR and you need it anyway?

@kevingranade
Copy link
Member

kevingranade commented Dec 3, 2016 via email

@mutability
Copy link
Contributor Author

Yeah, agreed that none of those solutions are particularly good; fixing the CI environment is the way forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants