Skip to content

replaced raw void* with std::any#1149

Draft
orange-cpp wants to merge 2 commits intoCrowCpp:masterfrom
orange-cpp:feaute/websocket_userdata_any
Draft

replaced raw void* with std::any#1149
orange-cpp wants to merge 2 commits intoCrowCpp:masterfrom
orange-cpp:feaute/websocket_userdata_any

Conversation

@orange-cpp
Copy link
Copy Markdown

@orange-cpp orange-cpp commented Feb 21, 2026

Updates the way user data is managed in the crow::websocket::connection class, replacing the use of raw pointers with a safer and more flexible and memory safe approach.

Improvements to user data handling:

  • Changed the userdata_ member from a void* to a std::any, allowing storage of arbitrary types and improving type safety.
  • Updated the userdata() setter and getter methods to use std::any instead of void*, enabling safer and more flexible user data management.

Why it's important:

CROW_WEBSOCKET_ROUTE(app, "/ws")
      .onopen([&](crow::websocket::connection& conn) {
          conn.userdata(std::make_shared<Foo>());
          CROW_LOG_INFO << "new websocket connection from " << conn.get_remote_ip();
          std::lock_guard<std::mutex> _(mtx);
          users.insert(&conn);
      })
      .onclose([&](crow::websocket::connection& conn, const std::string& reason, uint16_t) {
          CROW_LOG_INFO << "websocket connection closed: " << reason;
          std::lock_guard<std::mutex> _(mtx);
          users.erase(&conn);
      })
      .onmessage([&](crow::websocket::connection& /*conn*/, const std::string& data, bool is_binary) {
          std::lock_guard<std::mutex> _(mtx);
          for (auto u : users)
              if (is_binary)
                  u->send_binary(data);
              else
                  u->send_text(data);
      });

Output:

(2026-02-21 06:23:37) [INFO    ] Crow/master server is running at http://0.0.0.0:40080 using 28 threads
(2026-02-21 06:23:37) [INFO    ] Call `app.loglevel(crow::LogLevel::Warning)` to hide Info level logs.
Foo(): Allocated user data
(2026-02-21 06:23:38) [INFO    ] new websocket connection from 127.0.0.1
~Foo(): Deallocated user data
(2026-02-21 06:23:41) [INFO    ] websocket connection closed: 

You see client code can have huge .onclose handler and you can forgot call delete on object wich leads to memory leak or you can miss-cast type into something else and get UB wich is even worse.

@orange-cpp
Copy link
Copy Markdown
Author

Fixed missing #include <any> that fail fuzzing pipeline waiting for approval.

Copy link
Copy Markdown
Member

@gittiver gittiver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any has value characteristics, so there should be at least test to check if it behaves correctly?

@orange-cpp
Copy link
Copy Markdown
Author

any has value characteristics, so there should be at least test to check if it behaves correctly?

Tested it in my pet projects works very nicely, with smart pointers and any other types. Should be good to merge

@gittiver gittiver marked this pull request as draft April 1, 2026 20:59
@gittiver
Copy link
Copy Markdown
Member

gittiver commented Apr 1, 2026

set back to drift as no documentation and no tests were provided.

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.

2 participants