Skip to content

Fix uninitialized variable #3019

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

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from

Conversation

dzlaus
Copy link

@dzlaus dzlaus commented Jul 14, 2025

Have run into a very peculiar error on GCC 15.1 which only manifests when using with the following flags
'-Wall Werror=uninitialized -fhardened' and only under Release mode compilation.

The -fhardened flag is critical, as without it the compiler will happily compile the code. No idea what trips the compiler, but the fix is trivial.

The issue is reproducible on the WebSocket server, asynchronous example.

The full compiler output is as follows:

ninja
[1/2] Building CXX object CMakeFiles/unitialized_variable.dir/main.cpp.o
FAILED: CMakeFiles/unitialized_variable.dir/main.cpp.o 
/usr/lib/ccache/bin/g++   -O3 -DNDEBUG -std=gnu++26 -fdiagnostics-color=always -Wall -Werror=uninitialized -fhardened -MD -MT CMakeFiles/unitialized_variable.dir/main.cpp.o -MF CMakeFiles/unitialized_variable.dir/main.cpp.o.d -o CMakeFiles/unitialized_variable.dir/main.cpp.o -c /home/user/workspace/unitialized_variable/main.cpp
In file included from /usr/include/boost/endian/detail/endian_reverse.hpp:9,
                 from /usr/include/boost/endian/conversion.hpp:11,
                 from /usr/include/boost/beast/websocket/detail/frame.hpp:20,
                 from /usr/include/boost/beast/websocket/detail/impl_base.hpp:14,
                 from /usr/include/boost/beast/websocket/stream.hpp:20,
                 from /usr/include/boost/beast/websocket.hpp:18,
                 from /home/user/workspace/unitialized_variable/main.cpp:17:
In function ‘constexpr uint16_t boost::endian::detail::endian_reverse_impl(uint16_t)’,
    inlined from ‘constexpr typename std::enable_if<(! std::is_class<_Tp>::value), T>::type boost::endian::endian_reverse(T) [with T = short unsigned int]’ at /usr/include/boost/endian/detail/endian_reverse.hpp:131:55,
    inlined from ‘constexpr EndianReversible boost::endian::detail::conditional_reverse_impl(EndianReversible, std::false_type) [with EndianReversible = short unsigned int]’ at /usr/include/boost/endian/conversion.hpp:181:26,
    inlined from ‘constexpr EndianReversible boost::endian::conditional_reverse(EndianReversible) [with order From = boost::endian::order::big; order To = boost::endian::order::little; EndianReversible = short unsigned int]’ at /usr/include/boost/endian/conversion.hpp:191:44,
    inlined from ‘constexpr EndianReversible boost::endian::big_to_native(EndianReversible) [with EndianReversible = short unsigned int]’ at /usr/include/boost/endian/conversion.hpp:148:73,
    inlined from ‘void boost::beast::websocket::detail::read_close(boost::beast::websocket::close_reason&, const Buffers&, boost::beast::error_code&) [with Buffers = boost::beast::buffers_prefix_view<boost::beast::detail::buffers_pair<true> >]’ at /usr/include/boost/beast/websocket/detail/frame.hpp:224:36:
/usr/include/boost/endian/detail/endian_reverse.hpp:60:12: error: ‘code_be’ may be used uninitialized [-Werror=maybe-uninitialized]
   60 |     return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x);
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/beast/websocket/detail/frame.hpp: In function ‘void boost::beast::websocket::detail::read_close(boost::beast::websocket::close_reason&, const Buffers&, boost::beast::error_code&) [with Buffers = boost::beast::buffers_prefix_view<boost::beast::detail::buffers_pair<true> >]’:
/usr/include/boost/beast/websocket/detail/frame.hpp:216:19: note: ‘code_be’ was declared here
  216 |     std::uint16_t code_be;
      |                   ^~~~~~~
cc1plus: some warnings being treated as errors
ninja: build stopped: subcommand failed.

Error manifests when using GCC 15.1 with the following flags '-Wall Werror=uninitialized -fhardened'
@dzlaus dzlaus force-pushed the unitialized_variable branch from d3dc2d5 to 834ba23 Compare July 14, 2025 19:21
Copy link

codecov bot commented Jul 14, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 93.11%. Comparing base (03f0ff3) to head (44bc18a).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           develop    #3019   +/-   ##
========================================
  Coverage    93.11%   93.11%           
========================================
  Files          176      176           
  Lines        13643    13647    +4     
========================================
+ Hits         12704    12708    +4     
  Misses         939      939           
Files with missing lines Coverage Δ
include/boost/beast/websocket/detail/frame.hpp 100.00% <100.00%> (ø)
include/boost/beast/websocket/impl/stream_impl.hpp 96.21% <100.00%> (+0.02%) ⬆️

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 03f0ff3...44bc18a. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ashtum
Copy link
Collaborator

ashtum commented Jul 15, 2025

The following is minimal reproducible example of the same warning:
https://godbolt.org/z/9axKqv1PP

#include <boost/beast.hpp>

using namespace boost;

std::uint16_t
fun(
    asio::const_buffer const& cb,
    system::error_code& ec)
{
    if(cb.size() < 2)
        return 0;

    ec = {}; // commenting this line resolves warning

    std::uint16_t result;
    asio::buffer_copy(
        asio::mutable_buffer(&result, sizeof(result)),
        cb);
    return endian::big_to_native(result);
}

It seems the compiler thinks assigning to ec might change the buffer size.
There are a few other places in the code with the same issue. Zero initializing the variable is a workaround, but ideally, we want the compiler to reason about the code, since logically a zero initialized variable is not what we want either.

@ashtum
Copy link
Collaborator

ashtum commented Jul 17, 2025

For the record, I couldn't get the compiler to reason correctly about asio::buffer_copy. I used statements similar to if (buffer_bytes(bs) < 2) __builtin_unreachable(); to provide additional information to the compiler. While this worked in a few cases, it failed in two cases in stream_impl.hpp. Therefore, it seems more consistent to zero-initialize all of them instead.
https://godbolt.org/z/54GbYbr4a

#include <boost/beast.hpp>

using namespace boost;

std::uint16_t
fun(
    asio::const_buffer const& cb,
    system::error_code& ec)
{
    if(cb.size() < 2)
        return 0;

    ec = {};
    if(beast::buffer_bytes(cb) < 2) __builtin_unreachable();

    std::uint16_t result;
    asio::buffer_copy(
        asio::mutable_buffer(&result, sizeof(result)),
        cb);
    return endian::big_to_native(result);
}

These warnings are only triggered when a combination of
`-Wmaybe-uninitialized` and `-ftrivial-auto-var-init=zero` is used
with GCC 14.2 or later.
@ashtum ashtum force-pushed the unitialized_variable branch from 44bc18a to bc1fcf4 Compare July 17, 2025 15:27
@cppalliance-bot
Copy link

An automated preview of the documentation is available at https://3019.beast.prtest.cppalliance.org/libs/beast/doc/html/index.html

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.

3 participants