glfw/glfw

Dereference of NULL error according to GCC's -fanalyzer

Nostress767 opened this issue · 0 comments

OS and version: Linux archlinux 6.8.1-arch1-1 #1 SMP PREEMPT_DYNAMIC Sat, 16 Mar 2024 17:15:35 +0000 x86_64 GNU/Linux
Compiler version: gcc (GCC) 13.2.1 20230801
Release or commit: bf945f1

I run a small project using the flags "-fanalyzer -Werror -Wall -Wpedantic". When I tried adding GLFW to it, GCC's static analyzer flared up and gave me some errors. I'm not sure what they affect or how they interact with other things, but I tried replicating the issue from the latest commit with a minimal code example just to make sure and they still popped up.

I created the Makefile and main.c in the root directory of this project and ran make

Makefile:

# Disable built-in rules and variables
MAKEFLAGS += --no-builtin-rules
MAKEFLAGS += --no-builtin-variables

CC       := gcc
CPPFLAGS := -Iinclude -D_GLFW_X11
CFLAGS   := -fanalyzer -c
LDFLAGS  := -lm
EXE      := Example

OBJS := main.o
OBJS += src/context.o src/init.o src/input.o src/monitor.o src/platform.o src/window.o
OBJS += src/posix_module.o src/posix_thread.o src/posix_time.o src/posix_poll.o
OBJS += src/egl_context.o src/glx_context.o src/osmesa_context.o
OBJS += src/linux_joystick.o src/xkb_unicode.o
OBJS += src/vulkan.o
OBJS += src/x11_window.o src/x11_init.o src/x11_monitor.o
OBJS += src/null_init.o src/null_joystick.o src/null_monitor.o src/null_window.o

all: clean $(EXE)

$(OBJS) : %.o : %.c
	$(CC) $(CPPFLAGS) $(CFLAGS) $< -o $@

$(EXE): $(OBJS)
	$(CC) -o $@ $(OBJS) $(LDFLAGS)

clean:
	rm -f src/*.o $(EXE)

main.c:

#include "GLFW/glfw3.h"

#include <stdbool.h>

int main(int argc, char* argv[])
{
	glfwInit();

	GLFWwindow *window = glfwCreateWindow(800, 600, "Test", NULL, NULL);

	glfwMakeContextCurrent(window);

	while(!glfwWindowShouldClose(window)){
		glfwPollEvents();

		if(glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS)
			glfwSetWindowShouldClose(window, true);

		glfwSwapBuffers(window);
	}

	glfwTerminate();
}

Build log:

rm -f src/*.o Example
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/context.c -o src/context.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/init.c -o src/init.o
src/init.c: In function ‘_glfwInputError’:
src/init.c:366:25: warning: dereference of NULL ‘error’ [CWE-476] [-Wanalyzer-null-dereference]
  366 |             error->next = _glfw.errorListHead;
      |             ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
  ‘_glfwInputError’: events 1-6
    |
    |  309 | void _glfwInputError(int code, const char* format, ...)
    |      |      ^~~~~~~~~~~~~~~
    |      |      |
    |      |      (1) entry to ‘_glfwInputError’
    |......
    |  358 |     if (_glfw.initialized)
    |      |        ~
    |      |        |
    |      |        (2) following ‘true’ branch...
    |  359 |     {
    |  360 |         error = _glfwPlatformGetTls(&_glfw.errorSlot);
    |      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                 |
    |      |                 (3) ...to here
    |  361 |         if (!error)
    |      |            ~
    |      |            |
    |      |            (4) following ‘true’ branch (when ‘error’ is NULL)...
    |  362 |         {
    |  363 |             error = _glfw_calloc(1, sizeof(_GLFWerror));
    |      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                     |
    |      |                     (5) ...to here
    |      |                     (6) calling ‘_glfw_calloc’ from ‘_glfwInputError’
    |
    +--> ‘_glfw_calloc’: events 7-12
           |
           |  249 | void* _glfw_calloc(size_t count, size_t size)
           |      |       ^~~~~~~~~~~~
           |      |       |
           |      |       (7) entry to ‘_glfw_calloc’
           |  250 | {
           |  251 |     if (count && size)
           |      |        ~
           |      |        |
           |      |        (8) following ‘true’ branch...
           |......
           |  255 |         if (count > SIZE_MAX / size)
           |      |            ~~~~~~~~~~~~~~~~~~~~~~~~
           |      |            |      |
           |      |            |      (9) ...to here
           |      |            (10) following ‘true’ branch...
           |  256 |         {
           |  257 |             _glfwInputError(GLFW_INVALID_VALUE, "Allocation size overflow");
           |      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           |      |             |
           |      |             (11) ...to here
           |      |             (12) calling ‘_glfwInputError’ from ‘_glfw_calloc’
           |
           +--> ‘_glfwInputError’: events 13-19
                  |
                  |  309 | void _glfwInputError(int code, const char* format, ...)
                  |      |      ^~~~~~~~~~~~~~~
                  |      |      |
                  |      |      (13) entry to ‘_glfwInputError’
                  |......
                  |  314 |     if (format)
                  |      |        ~
                  |      |        |
                  |      |        (14) following ‘true’ branch (when ‘format’ is non-NULL)...
                  |......
                  |  318 |         va_start(vl, format);
                  |      |         ~~~~~~~~
                  |      |         |
                  |      |         (15) ...to here
                  |......
                  |  358 |     if (_glfw.initialized)
                  |      |        ~
                  |      |        |
                  |      |        (16) following ‘false’ branch...
                  |......
                  |  372 |         error = &_glfwMainThreadError;
                  |      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  |      |               |
                  |      |               (17) ...to here
                  |......
                  |  377 |     if (_glfwErrorCallback)
                  |      |        ~
                  |      |        |
                  |      |        (18) following ‘false’ branch...
                  |  378 |         _glfwErrorCallback(code, description);
                  |  379 | }
                  |      | ~     
                  |      | |
                  |      | (19) ...to here
                  |
           <------+
           |
         ‘_glfw_calloc’: event 20
           |
           |  257 |             _glfwInputError(GLFW_INVALID_VALUE, "Allocation size overflow");
           |      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           |      |             |
           |      |             (20) returning to ‘_glfw_calloc’ from ‘_glfwInputError’
           |
         ‘_glfw_calloc’: event 21
           |
           |  258 |             return NULL;
           |      |                    ^~~~
           |      |                    |
           |      |                    (21) ‘0’ is NULL
           |
    <------+
    |
  ‘_glfwInputError’: events 22-24
    |
    |  363 |             error = _glfw_calloc(1, sizeof(_GLFWerror));
    |      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                     |
    |      |                     (22) returning to ‘_glfwInputError’ from ‘_glfw_calloc’
    |......
    |  366 |             error->next = _glfw.errorListHead;
    |      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                         |
    |      |                         (24) dereference of NULL ‘error’
    |  367 |             _glfw.errorListHead = error;
    |      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                 |
    |      |                                 (23) ‘error’ is NULL
    |
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/input.c -o src/input.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/monitor.c -o src/monitor.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/platform.c -o src/platform.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/window.c -o src/window.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/posix_module.c -o src/posix_module.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/posix_thread.c -o src/posix_thread.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/posix_time.c -o src/posix_time.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/posix_poll.c -o src/posix_poll.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/egl_context.c -o src/egl_context.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/glx_context.c -o src/glx_context.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/osmesa_context.c -o src/osmesa_context.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/linux_joystick.c -o src/linux_joystick.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/xkb_unicode.c -o src/xkb_unicode.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/vulkan.c -o src/vulkan.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/x11_window.c -o src/x11_window.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/x11_init.c -o src/x11_init.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/x11_monitor.c -o src/x11_monitor.o
src/x11_monitor.c: In function ‘modeIsGood’:
src/x11_monitor.c:42:15: warning: dereference of NULL ‘mi’ [CWE-476] [-Wanalyzer-null-dereference]
   42 |     return (mi->modeFlags & RR_Interlace) == 0;
      |             ~~^~~~~~~~~~~
  ‘_glfwGetVideoModesX11’: events 1-2
    |
    |  442 | GLFWvidmode* _glfwGetVideoModesX11(_GLFWmonitor* monitor, int* count)
    |      |              ^~~~~~~~~~~~~~~~~~~~~
    |      |              |
    |      |              (1) entry to ‘_glfwGetVideoModesX11’
    |......
    |  448 |     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    |      |        ~      
    |      |        |
    |      |        (2) following ‘true’ branch...
    |
  ‘_glfwGetVideoModesX11’: event 3
    |
    |src/x11_platform.h:329:53:
    |  329 | #define XRRGetScreenResourcesCurrent _glfw.x11.randr.GetScreenResourcesCurrent
    |      |                                      ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                                     |
    |      |                                                     (3) ...to here
src/x11_monitor.c:451:13: note: in expansion of macro ‘XRRGetScreenResourcesCurrent’
    |  451 |             XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
    |      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |
  ‘_glfwGetVideoModesX11’: events 4-6
    |
    |  457 |         for (int i = 0;  i < oi->nmode;  i++)
    |      |                          ~~^~~~~~~~~~~
    |      |                            |
    |      |                            (4) following ‘true’ branch...
    |  458 |         {
    |  459 |             const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
    |      |                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                     |                 |
    |      |                                     |                 (5) ...to here
    |      |                                     (6) calling ‘getModeInfo’ from ‘_glfwGetVideoModesX11’
    |
    +--> ‘getModeInfo’: event 7
           |
           |   57 | static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
           |      |                           ^~~~~~~~~~~
           |      |                           |
           |      |                           (7) entry to ‘getModeInfo’
           |
         ‘getModeInfo’: event 8
           |
           |   65 |     return NULL;
           |      |            ^~~~
           |      |            |
           |      |            (8) ‘0’ is NULL
           |
    <------+
    |
  ‘_glfwGetVideoModesX11’: events 9-10
    |
    |  459 |             const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
    |      |                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                     |
    |      |                                     (9) return of NULL to ‘_glfwGetVideoModesX11’ from ‘getModeInfo’
    |  460 |             if (!modeIsGood(mi))
    |      |                  ~~~~~~~~~~~~~~      
    |      |                  |
    |      |                  (10) calling ‘modeIsGood’ from ‘_glfwGetVideoModesX11’
    |
    +--> ‘modeIsGood’: events 11-12
           |
           |   40 | static GLFWbool modeIsGood(const XRRModeInfo* mi)
           |      |                 ^~~~~~~~~~
           |      |                 |
           |      |                 (11) entry to ‘modeIsGood’
           |   41 | {
           |   42 |     return (mi->modeFlags & RR_Interlace) == 0;
           |      |             ~~~~~~~~~~~~~
           |      |               |
           |      |               (12) dereference of NULL ‘mi’
           |
src/x11_monitor.c: In function ‘_glfwPollMonitorsX11’:
src/x11_monitor.c:180:31: warning: dereference of NULL ‘screens’ [CWE-476] [-Wanalyzer-null-dereference]
  180 |                 if (screens[j].x_org == ci->x &&
      |                     ~~~~~~~~~~^~~~~~
  ‘_glfwPollMonitorsX11’: events 1-8
    |
    |  103 |     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    |      |        ^
    |      |        |
    |      |        (1) following ‘true’ branch...
    |  104 |     {
    |  105 |         int disconnectedCount, screenCount = 0;
    |      |                                ~~~~~~~~~~~
    |      |                                |
    |      |                                (2) ...to here
    |  106 |         _GLFWmonitor** disconnected = NULL;
    |  107 |         XineramaScreenInfo* screens = NULL;
    |      |                             ~~~~~~~
    |      |                             |
    |      |                             (3) ‘screens’ is NULL
    |......
    |  113 |         if (_glfw.x11.xinerama.available)
    |      |            ~
    |      |            |
    |      |            (4) following ‘false’ branch...
    |......
    |  116 |         disconnectedCount = _glfw.monitorCount;
    |      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                           |
    |      |                           (5) ...to here
    |  117 |         if (disconnectedCount)
    |      |            ~
    |      |            |
    |      |            (6) following ‘false’ branch (when ‘disconnectedCount == 0’)...
    |......
    |  125 |         for (int i = 0;  i < sr->noutput;  i++)
    |      |                  ~       ~~~~~~~~~~~~~~~
    |      |                  |         |
    |      |                  |         (8) following ‘true’ branch...
    |      |                  (7) ...to here
    |
  ‘_glfwPollMonitorsX11’: event 9
    |
    |src/x11_platform.h:327:41:
    |  327 | #define XRRGetOutputInfo _glfw.x11.randr.GetOutputInfo
    |      |                          ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
    |      |                                         |
    |      |                                         (9) ...to here
src/x11_monitor.c:129:33: note: in expansion of macro ‘XRRGetOutputInfo’
    |  129 |             XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
    |      |                                 ^~~~~~~~~~~~~~~~
    |
  ‘_glfwPollMonitorsX11’: events 10-14
    |
    |  130 |             if (oi->connection != RR_Connected || oi->crtc == None)
    |      |                ^
    |      |                |
    |      |                (10) following ‘false’ branch...
    |......
    |  136 |             for (j = 0;  j < disconnectedCount;  j++)
    |      |                  ~~~~~   ~~~~~~~~~~~~~~~~~~~~~
    |      |                    |       |
    |      |                    |       (12) following ‘false’ branch (when ‘j >= disconnectedCount’)...
    |      |                    (11) ...to here
    |......
    |  146 |             if (j < disconnectedCount)
    |      |                ~
    |      |                |
    |      |                (13) ...to here
    |      |                (14) following ‘false’ branch (when ‘j >= disconnectedCount’)...
    |
  ‘_glfwPollMonitorsX11’: event 15
    |
    |src/x11_platform.h:326:39:
    |  326 | #define XRRGetCrtcInfo _glfw.x11.randr.GetCrtcInfo
    |      |                        ~~~~~~~~~~~~~~~^~~~~~~~~~~~
    |      |                                       |
    |      |                                       (15) ...to here
src/x11_monitor.c:152:31: note: in expansion of macro ‘XRRGetCrtcInfo’
    |  152 |             XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
    |      |                               ^~~~~~~~~~~~~~
    |
  ‘_glfwPollMonitorsX11’: events 16-19
    |
    |  178 |             for (j = 0;  j < screenCount;  j++)
    |      |                          ~~^~~~~~~~~~~~~
    |      |                            |
    |      |                            (16) following ‘true’ branch...
    |  179 |             {
    |  180 |                 if (screens[j].x_org == ci->x &&
    |      |                     ~~~~~~~~~~~~~~~~
    |      |                            |  |
    |      |                            |  (19) dereference of NULL ‘screens + (long unsigned int)j * 12’
    |      |                            (17) ...to here
    |      |                            (18) ‘screens’ is NULL
    |
src/x11_monitor.c: In function ‘_glfwGetMonitorWorkareaX11’:
src/x11_monitor.c:367:28: warning: dereference of NULL ‘mi’ [CWE-476] [-Wanalyzer-null-dereference]
  367 |             areaWidth  = mi->height;
      |                          ~~^~~~~~~~
  ‘_glfwGetMonitorWorkareaX11’: events 1-2
    |
    |  348 | void _glfwGetMonitorWorkareaX11(_GLFWmonitor* monitor,
    |      |      ^~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |      |
    |      |      (1) entry to ‘_glfwGetMonitorWorkareaX11’
    |......
    |  354 |     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    |      |        ~
    |      |        |
    |      |        (2) following ‘true’ branch...
    |
  ‘_glfwGetMonitorWorkareaX11’: event 3
    |
    |src/x11_platform.h:329:53:
    |  329 | #define XRRGetScreenResourcesCurrent _glfw.x11.randr.GetScreenResourcesCurrent
    |      |                                      ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                                     |
    |      |                                                     (3) ...to here
src/x11_monitor.c:357:13: note: in expansion of macro ‘XRRGetScreenResourcesCurrent’
    |  357 |             XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
    |      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |
  ‘_glfwGetMonitorWorkareaX11’: event 4
    |
    |  363 |         const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
    |      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                 |
    |      |                                 (4) calling ‘getModeInfo’ from ‘_glfwGetMonitorWorkareaX11’
    |
    +--> ‘getModeInfo’: event 5
           |
           |   57 | static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
           |      |                           ^~~~~~~~~~~
           |      |                           |
           |      |                           (5) entry to ‘getModeInfo’
           |
         ‘getModeInfo’: event 6
           |
           |   65 |     return NULL;
           |      |            ^~~~
           |      |            |
           |      |            (6) ‘0’ is NULL
           |
    <------+
    |
  ‘_glfwGetMonitorWorkareaX11’: events 7-8
    |
    |  363 |         const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
    |      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                 |
    |      |                                 (7) return of NULL to ‘_glfwGetMonitorWorkareaX11’ from ‘getModeInfo’
    |......
    |  367 |             areaWidth  = mi->height;
    |      |                          ~~~~~~~~~~
    |      |                            |
    |      |                            (8) dereference of NULL ‘mi’
    |
src/x11_monitor.c:372:28: warning: dereference of NULL ‘mi’ [CWE-476] [-Wanalyzer-null-dereference]
  372 |             areaWidth  = mi->width;
      |                          ~~^~~~~~~
  ‘_glfwGetMonitorWorkareaX11’: events 1-2
    |
    |  348 | void _glfwGetMonitorWorkareaX11(_GLFWmonitor* monitor,
    |      |      ^~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |      |
    |      |      (1) entry to ‘_glfwGetMonitorWorkareaX11’
    |......
    |  354 |     if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    |      |        ~
    |      |        |
    |      |        (2) following ‘true’ branch...
    |
  ‘_glfwGetMonitorWorkareaX11’: event 3
    |
    |src/x11_platform.h:329:53:
    |  329 | #define XRRGetScreenResourcesCurrent _glfw.x11.randr.GetScreenResourcesCurrent
    |      |                                      ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                                     |
    |      |                                                     (3) ...to here
src/x11_monitor.c:357:13: note: in expansion of macro ‘XRRGetScreenResourcesCurrent’
    |  357 |             XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
    |      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |
  ‘_glfwGetMonitorWorkareaX11’: event 4
    |
    |  363 |         const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
    |      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                 |
    |      |                                 (4) calling ‘getModeInfo’ from ‘_glfwGetMonitorWorkareaX11’
    |
    +--> ‘getModeInfo’: event 5
           |
           |   57 | static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
           |      |                           ^~~~~~~~~~~
           |      |                           |
           |      |                           (5) entry to ‘getModeInfo’
           |
         ‘getModeInfo’: event 6
           |
           |   65 |     return NULL;
           |      |            ^~~~
           |      |            |
           |      |            (6) ‘0’ is NULL
           |
    <------+
    |
  ‘_glfwGetMonitorWorkareaX11’: events 7-10
    |
    |  363 |         const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
    |      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                 |
    |      |                                 (7) return of NULL to ‘_glfwGetMonitorWorkareaX11’ from ‘getModeInfo’
    |  364 | 
    |  365 |         if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
    |      |            ~                     
    |      |            |
    |      |            (8) following ‘false’ branch...
    |......
    |  372 |             areaWidth  = mi->width;
    |      |                          ~~~~~~~~~
    |      |                            |
    |      |                            (9) ...to here
    |      |                            (10) dereference of NULL ‘mi’
    |
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/null_init.c -o src/null_init.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/null_joystick.c -o src/null_joystick.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/null_monitor.c -o src/null_monitor.o
gcc -Iinclude -D_GLFW_X11 -fanalyzer -c src/null_window.c -o src/null_window.o
gcc -o Example main.o src/context.o src/init.o src/input.o src/monitor.o src/platform.o src/window.o src/posix_module.o src/posix_thread.o src/posix_time.o src/posix_poll.o src/egl_context.o src/glx_context.o src/osmesa_context.o src/linux_joystick.o src/xkb_unicode.o src/vulkan.o src/x11_window.o src/x11_init.o src/x11_monitor.o src/null_init.o src/null_joystick.o src/null_monitor.o src/null_window.o -lm