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

<algorithm>: /analyze with ranges algorithms emits fatal error C1060: compiler is out of heap space #1030

Open
StephanTLavavej opened this issue Jul 11, 2020 · 3 comments
Labels
bug Something isn't working

Comments

@StephanTLavavej
Copy link
Member

StephanTLavavej commented Jul 11, 2020

We've been encountering a recurring problem where testing the ranges algorithms with /analyze will fail with fatal error C1060: compiler is out of heap space. Specifically, the trigger seems to be constexpr testing of ranges algorithms with /analyze. Take P0896R4_ranges_alg_move for example:

struct instantiator {
    static constexpr int_wrapper expected_output[3] = {13, 55, 12345};
    static constexpr int_wrapper expected_input[3]  = {-1, -1, -1};

    template <ranges::input_range Read, indirectly_writable<ranges::range_rvalue_reference_t<Read>> Write>
    static constexpr void call() {
#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-938163
#pragma warning(suppress : 4127) //  conditional expression is constant
        if (!ranges::contiguous_range<Read> || !is_constant_evaluated())
#endif // TRANSITION, VSO-938163
        {
            using ranges::move, ranges::move_result, ranges::equal, ranges::iterator_t;
            {
                int_wrapper input[3]  = {13, 55, 12345};
                int_wrapper output[3] = {-2, -2, -2};
                Read wrapped_input{input};

                auto result = move(wrapped_input, Write{output});
                STATIC_ASSERT(same_as<decltype(result), move_result<iterator_t<Read>, Write>>);
                assert(result.in == wrapped_input.end());
                assert(result.out.peek() == output + 3);
                assert(equal(output, expected_output));
                assert(equal(input, expected_input));
            }
            {
                int_wrapper input[3]  = {13, 55, 12345};
                int_wrapper output[3] = {-2, -2, -2};
                Read wrapped_input{input};

                auto result = move(wrapped_input.begin(), wrapped_input.end(), Write{output});
                STATIC_ASSERT(same_as<decltype(result), move_result<iterator_t<Read>, Write>>);
                assert(result.in == wrapped_input.end());
                assert(result.out.peek() == output + 3);
                assert(equal(output, expected_output));
                assert(equal(input, expected_input));
            }
        }
    }
};

int main() {
    STATIC_ASSERT((test_in_write<instantiator, int_wrapper, int_wrapper>(), true)); // ***CONSTEXPR TEST***
    test_in_write<instantiator, int_wrapper, int_wrapper>();
}

test_in_write<instantiator, int_wrapper, int_wrapper>() calls instantiator::call with 825 different combinations of template arguments to get test coverage of virtually every possible combination of range argument properties. Compiling this test with /analyze exhausts the compiler heap resulting in C1060. It compiles fine if we comment out the // ***CONSTEXPR TEST*** line, but produces the same error if we comment out only the next non-constexpr test line. There's no clear reason why virtually the same code should require vastly more memory to analyze when it happens to be called in a constant expression vs. not. Indeed it's not clear to me why that distinction would affect the static analyzer at all.

We'll work around this for the time being by conditionally compiling the constexpr test only when _PREFAST_ is not defined, which indicates that /analyze is not enabled. @CaseyCarter will try to reduce a simpler test case and submit a static analyzer bug on Developer Community.

@AlexGuteniev
Copy link
Contributor

AlexGuteniev commented Jul 11, 2020

I've seen this with VS2015.
Large project is /analyzed by processing .cpp files one by one, and it seems to leak memory on each. Specifically, I observed that precompiled header is never unmapped, resulting in many copies of it.
I ended up setting large enough swap file (switching to using x64 toolset even for 32-bit x86 was done already by that time)

StephanTLavavej added a commit that referenced this issue Jul 11, 2020
This is a temporary workaround for #1030 to unblock ranges PRs.
CaseyCarter added a commit to CaseyCarter/STL that referenced this issue Jul 12, 2020
CaseyCarter added a commit to CaseyCarter/STL that referenced this issue Jul 12, 2020
Workaround VSO-938163 in triggered in `P0896R4_ranges_alg_move` as well.

Remove `/analyze` "help" from ranges tests.

Re-enable `/analyze:only` coverage in `concepts_matrix.lst`.

Apply improved workaround for microsoftGH-1030: don't test `constexpr` under `/analyze`.

Add missing return type check in `P0896R4_ranges_alg_move`.
@StephanTLavavej
Copy link
Member Author

That might have a different root cause (as these tests are single-TU). If it still repros with VS 2019, it's probably worth reporting.

Configuring our CI system to use x64-hosted x86-targeting binaries might be a mitigation, but it would be invasive. Reporting the ranges/concepts interaction to the analyze team, and using a targeted workaround, is probably less disruptive.

@cbezault
Copy link
Contributor

Yeah changing the CI so that we could use the x64/x86 cross-compiler for tests other than tests with the /BE flag would be a pain.

CaseyCarter added a commit to CaseyCarter/STL that referenced this issue Jul 16, 2020
CaseyCarter added a commit to CaseyCarter/STL that referenced this issue Aug 27, 2020
CaseyCarter added a commit to CaseyCarter/STL that referenced this issue Aug 28, 2020
This is the last test for which I've heard complaints about memory usage.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants