Track newmenu return value using std::shared_ptr

JoeNotCharles reports that gcc-12 (architecture unspecified) warns
because `newmenu::process_until_closed` stores the address of a stack
local into a heap-allocated structure.  Switch to a less efficient
implementation that does not provoke a compiler warning:

- Store `shared_ptr<int>`, not `int *`, in the `newmenu`
- `shared_ptr::operator*()` and `shared_ptr::operator bool()` allow most
  use sites to be unchanged relative to a bare pointer
- Load the return value from the `shared_ptr<int>`.  If the newmenu
  terminated before return, as should always happen, this is a slightly
  less efficient version of the same code as before.  If the newmenu was
  still open despite its `exists` flag claiming otherwise, then the
  returned value may be incorrect, but the read will be well-formed, the
  `newmenu`'s eventual write will write to the heap-backed int (rather
  than writing into the stack allocated to
  `newmenu::process_until_closed`), and the memory will be freed when
  both `process_until_closed` has returned and the `newmenu` has been
  destroyed.

Reported-by: JoeNotCharles <10a2b2d337>
This commit is contained in:
Kp 2023-01-14 19:05:37 +00:00
parent 407ab585a8
commit 27586fe0b9
2 changed files with 4 additions and 4 deletions

View file

@ -354,7 +354,7 @@ struct newmenu : newmenu_layout, window, mixin_trackable_window
newmenu_layout(title, subtitle, filename, src, tiny_mode, tabs_flag, citem_init, draw_box), window(src, x, y, w, h)
{
}
int *rval = nullptr; // Pointer to return value (for polling newmenus)
std::shared_ptr<int> rval; // Pointer to return value (for polling newmenus)
virtual window_event_result event_handler(const d_event &) override;
static int process_until_closed(newmenu *);
};

View file

@ -534,8 +534,8 @@ int newmenu_do2(const menu_title title, const menu_subtitle subtitle, const rang
int newmenu::process_until_closed(newmenu *const menu)
{
int rval = -1;
menu->rval = &rval;
auto rval = std::make_shared<int>(-1);
menu->rval = rval;
// Track to see when the window is freed
// Doing this way in case another window is opened on top without its own polling loop
// newmenu_do2 and simpler get their own event loop
@ -546,7 +546,7 @@ int newmenu::process_until_closed(newmenu *const menu)
/* menu is now a pointer to freed memory, and cannot be accessed
* further
*/
return rval;
return *rval;
}
namespace {