• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devmarkusb / util / 23412147180

22 Mar 2026 08:46PM UTC coverage: 88.237% (+0.009%) from 88.228%
23412147180

push

github

MarkusB
Add `pin_heap_allocation` to prevent GCC optimizations affecting `new`/`delete` statistics in tests

5 of 5 new or added lines in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

5821 of 6597 relevant lines covered (88.24%)

346.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.72
/mem/src/new_statistics.test.cpp
1
#include "ul/mem/new_statistics.h"
2
#include "ul/assert.h"
3
#include "ul/error.h"
4
#include "ul/mem/compiler_quirks.h"
5
#include "ul/mem/types.h"
6
#include <iostream>
7
#include <memory>
8
#include <vector>
9

10
namespace ul = mb::ul;
11

12
namespace {
13
/** GCC at high optimization can remove `new`/`delete` pairs when no *standard-observable* use of the
14
    storage remains; our Statistics hooks are not visible to the optimizer, so counts would stay at 0. */
15
void pin_heap_allocation([[maybe_unused]] void* p) noexcept {
2✔
16
#if defined(__GNUC__)
17
    asm volatile("" : : "g"(p) : "memory");
2✔
18
#endif
19
}
2✔
20
} // namespace
21

22
int main() {
1✔
23
    try {
24
        std::cout << "Running main() from " << __FILE__ << "\n";
1✔
25

26
        const auto& memstats = ul::mem::Statistics::instance();
1✔
27

28
        UL_ASSERT_THROW(memstats.new_calls() == 0);
1✔
29
        UL_ASSERT_THROW(memstats.delete_calls() == 0);
1✔
30
        UL_ASSERT_THROW(memstats.peak_size() == ul::mem::Bytes{});
1✔
31

32
        size_t exp_new_calls{};
1✔
33
        size_t exp_delete_calls{};
1✔
34
        ul::mem::Bytes exp_peak_size{};
1✔
35
        constexpr auto n10{10};
1✔
36
        constexpr auto b44{44};
1✔
37
        {
38
            // RAII so we don't leak on assertion failure (e.g. during CMake test discovery)
39
            std::unique_ptr<int> p1(new int); // NOLINT
1✔
40
            pin_heap_allocation(p1.get());
1✔
41
            UL_ASSERT_THROW(memstats.new_calls() == 1u);
1✔
42
            UL_ASSERT_THROW(memstats.peak_size() == ul::mem::Bytes{4});
1✔
43

44
            auto impl_correction_ofs = memstats.allocated_size();
1✔
45
            {
46
                std::vector<int> l;
1✔
47
                impl_correction_ofs = memstats.allocated_size() - impl_correction_ofs;
1✔
48
                // just out of interest
49
                UL_ASSERT_THROW(impl_correction_ofs == ul::mem::quirk::vector::constr_heap_alloc_size);
1✔
50
                UL_ASSERT_THROW(!l.capacity());
1✔
51
                l.reserve(n10);
1✔
52
                exp_new_calls = 2 + (impl_correction_ofs ? 1 : 0);
1✔
53
                UL_ASSERT_THROW(memstats.new_calls() == exp_new_calls);
1✔
54
                exp_peak_size = ul::mem::Bytes{b44} + impl_correction_ofs;
1✔
55
                UL_ASSERT_THROW(memstats.peak_size() == exp_peak_size);
1✔
56
                for (int i = 0; i < n10 / 2; ++i)
6✔
57
                    l.push_back(i);
5✔
58
            }
1✔
59
            exp_delete_calls = 1 + (impl_correction_ofs ? 1 : 0);
1✔
60
            UL_ASSERT_THROW(memstats.delete_calls() == exp_delete_calls);
1✔
61

62
            p1.reset(); // calls delete, so stats still updated
1✔
63
            ++exp_delete_calls;
1✔
64
            UL_ASSERT_THROW(memstats.delete_calls() == exp_delete_calls);
1✔
65

66
            UL_ASSERT_THROW(memstats.peak_size() == ul::mem::Bytes{b44} + impl_correction_ofs);
1✔
67

68
            std::unique_ptr<int[]> p2(new int[n10]); // NOLINT
1✔
69
            pin_heap_allocation(p2.get());
1✔
70
            ++exp_new_calls;
1✔
71
            UL_ASSERT_THROW(memstats.new_calls() == exp_new_calls);
1✔
72
            p2.reset(); // calls delete[], stats still updated
1✔
73
            ++exp_delete_calls;
1✔
74
            UL_ASSERT_THROW(memstats.delete_calls() == exp_delete_calls);
1✔
75
        }
1✔
76

77
        UL_ASSERT_THROW(memstats.new_calls() == exp_new_calls);
1✔
78
        UL_ASSERT_THROW(memstats.delete_calls() == exp_delete_calls);
1✔
79
        UL_ASSERT_THROW(memstats.peak_size() == exp_peak_size);
1✔
80

81
        std::cout << "PASSED (" << __FILE__ << ")\n";
1✔
82

83
        return ul::prog_exit_success;
1✔
UNCOV
84
    } catch (const std::exception& e) {
×
85
        std::cerr << "FAILED: " << e.what() << "\n";
×
86
        return ul::prog_exit_failure;
×
87
    } catch (...) {
×
88
        std::cerr << "FAILED: unknown exception\n";
×
89
        return ul::prog_exit_failure;
×
90
    }
×
91
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc