Change window allocation/destruction to avoid undefined behaviour

Create a new window base class which holds the front/back pointers
and the window class.
This fixes the voluminous warning spam about deleted windows when using
UndefinedBehaviorSanitizer.
pull/59/head
Jonathan G Rennison 6 years ago
parent d8ab61cab3
commit 6573a67b69

@ -480,7 +480,7 @@ static void SetViewportPosition(Window *w, int x, int y, bool force_update_overl
i = top + height - _screen.height;
if (i >= 0) height -= i;
if (height > 0) DoSetViewportPosition(w->z_front, left, top, width, height);
if (height > 0) DoSetViewportPosition((const Window *) w->z_front, left, top, width, height);
}
}

@ -52,9 +52,9 @@ static Window *_mouseover_last_w = NULL; ///< Window of the last #MOUSEOVER even
static Window *_last_scroll_window = NULL; ///< Window of the last scroll event.
/** List of windows opened at the screen sorted from the front. */
Window *_z_front_window = NULL;
WindowBase *_z_front_window = NULL;
/** List of windows opened at the screen sorted from the back. */
Window *_z_back_window = NULL;
WindowBase *_z_back_window = NULL;
/** If false, highlight is white, otherwise the by the widget defined colour. */
bool _window_highlight_colour = false;
@ -1359,7 +1359,7 @@ static void AddWindowToZOrdering(Window *w)
w->z_front = w->z_back = NULL;
} else {
/* Search down the z-ordering for its location. */
Window *v = _z_front_window;
WindowBase *v = _z_front_window;
uint last_z_priority = UINT_MAX;
while (v != NULL && (v->window_class == WC_INVALID || GetWindowZPriority(v->window_class) > GetWindowZPriority(w->window_class))) {
if (v->window_class != WC_INVALID) {
@ -1398,7 +1398,7 @@ static void AddWindowToZOrdering(Window *w)
* Removes a window from the z-ordering.
* @param w Window to remove
*/
static void RemoveWindowFromZOrdering(Window *w)
static void RemoveWindowFromZOrdering(WindowBase *w)
{
if (w->z_front == NULL) {
assert(_z_front_window == w);
@ -1897,11 +1897,11 @@ void UnInitWindowSystem()
{
UnshowCriticalError();
Window *w;
FOR_ALL_WINDOWS_FROM_FRONT(w) delete w;
Window *v;
FOR_ALL_WINDOWS_FROM_FRONT(v) delete v;
for (w = _z_front_window; w != NULL; /* nothing */) {
Window *to_del = w;
for (WindowBase *w = _z_front_window; w != NULL; /* nothing */) {
WindowBase *to_del = w;
w = w->z_back;
free(to_del);
}
@ -3080,8 +3080,8 @@ void InputLoop()
HandleKeyScrolling();
/* Do the actual free of the deleted windows. */
for (Window *v = _z_front_window; v != NULL; /* nothing */) {
Window *w = v;
for (WindowBase *v = _z_front_window; v != NULL; /* nothing */) {
WindowBase *w = v;
v = v->z_back;
if (w->window_class != WC_INVALID) continue;

@ -145,8 +145,8 @@ void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, Fra
void DrawCaption(const Rect &r, Colours colour, Owner owner, StringID str);
/* window.cpp */
extern Window *_z_front_window;
extern Window *_z_back_window;
extern WindowBase *_z_front_window;
extern WindowBase *_z_back_window;
extern Window *_focused_window;
inline uint64 GetWindowUpdateNumber()
@ -277,10 +277,48 @@ struct ViewportData : ViewPort {
struct QueryString;
struct WindowBase {
WindowBase *z_front; ///< The window in front of us in z-order.
WindowBase *z_back; ///< The window behind us in z-order.
WindowClass window_class; ///< Window class
virtual ~WindowBase() {}
/**
* Memory allocator for a single class instance.
* @param size the amount of bytes to allocate.
* @return the given amounts of bytes zeroed.
*/
inline void *operator new(size_t size) { return CallocT<byte>(size); }
protected:
WindowBase() {}
private:
/**
* Memory allocator for an array of class instances.
* @param size the amount of bytes to allocate.
* @return the given amounts of bytes zeroed.
*/
inline void *operator new[](size_t size) { NOT_REACHED(); }
/**
* Memory release for a single class instance.
* @param ptr the memory to free.
*/
inline void operator delete(void *ptr) { NOT_REACHED(); }
/**
* Memory release for an array of class instances.
* @param ptr the memory to free.
*/
inline void operator delete[](void *ptr) { NOT_REACHED(); }
};
/**
* Data structure for an opened window
*/
struct Window : ZeroedMemoryAllocator {
struct Window : WindowBase {
protected:
void InitializeData(WindowNumber window_number);
void InitializePositionSize(int x, int y, int min_width, int min_height);
@ -315,7 +353,6 @@ public:
WindowDesc *window_desc; ///< Window description
WindowFlags flags; ///< Window flags
WindowClass window_class; ///< Window class
WindowNumber window_number; ///< Window number within the window class
uint8 timeout_timer; ///< Timer value of the WF_TIMEOUT for flags.
@ -342,8 +379,6 @@ public:
int scrolling_scrollbar; ///< Widgetindex of just being dragged scrollbar. -1 if none is active.
Window *parent; ///< Parent window.
Window *z_front; ///< The window in front of us in z-order.
Window *z_back; ///< The window behind us in z-order.
template <class NWID>
inline const NWID *GetWidget(uint widnum) const;
@ -891,9 +926,37 @@ void GuiShowTooltips(Window *parent, StringID str, uint paramcount = 0, const ui
/* widget.cpp */
int GetWidgetFromPos(const Window *w, int x, int y);
inline const Window *FromBaseWindowFront(const WindowBase *w)
{
while (w) {
if (w->window_class != WC_INVALID) return (const Window *) w;
w = w->z_front;
}
return nullptr;
}
inline Window *FromBaseWindowFront(WindowBase *w)
{
return const_cast<Window *>(FromBaseWindowFront(const_cast<const WindowBase *>(w)));
}
inline const Window *FromBaseWindowBack(const WindowBase *w)
{
while (w) {
if (w->window_class != WC_INVALID) return (const Window *) w;
w = w->z_back;
}
return nullptr;
}
inline Window *FromBaseWindowBack(WindowBase *w)
{
return const_cast<Window *>(FromBaseWindowBack(const_cast<const WindowBase *>(w)));
}
/** Iterate over all windows */
#define FOR_ALL_WINDOWS_FROM_BACK_FROM(w, start) for (w = start; w != NULL; w = w->z_front) if (w->window_class != WC_INVALID)
#define FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, start) for (w = start; w != NULL; w = w->z_back) if (w->window_class != WC_INVALID)
#define FOR_ALL_WINDOWS_FROM_BACK_FROM(w, start) for (w = FromBaseWindowFront(start); w != NULL; w = FromBaseWindowFront(w->z_front))
#define FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, start) for (w = FromBaseWindowBack(start); w != NULL; w = FromBaseWindowBack(w->z_back))
#define FOR_ALL_WINDOWS_FROM_BACK(w) FOR_ALL_WINDOWS_FROM_BACK_FROM(w, _z_back_window)
#define FOR_ALL_WINDOWS_FROM_FRONT(w) FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, _z_front_window)

@ -755,6 +755,7 @@ enum GameOptionsInvalidationData {
};
struct Window;
struct WindowBase;
/** Number to differentiate different windows of the same class */
typedef int32 WindowNumber;

Loading…
Cancel
Save