Nuklear icon indicating copy to clipboard operation
Nuklear copied to clipboard

many code paths use asserts and null checks for the same thing at the same time

Open sleeptightAnsiC opened this issue 2 months ago • 3 comments

Nuklear uses following pattern through its source tree:

NK_ASSERT(foo);
NK_ASSERT(bar);
if (!foo || !bar) return;

(where foo and bar are pointers / arguments to some function)

example: https://github.com/Immediate-Mode-UI/Nuklear/blob/171090c8e21584330207544dbde5e7c1ec581135/src/nuklear_buffer.c#L38-L41

This is confusing in many places because (a) there are functions that I would expect to take NULL, e.g. any destructor, but those crash due to assert failing, (b) if a code works just fine with a null check, why does it need to be guarded with assert? and (c) if developer is never able to test those checks, they're not really useful.

I could point to few locations where it does not make much sense. For example nk_font_atlas_clear should work when passing NULL or empty atlas, but the assert causes an unexpected crash [reference]

Is there some specific reason why Nuklear uses this idiom?


For reference, almost every occurrence of this pattern can be found with following AWK script:

Details

$ git clone https://github.com/Immediate-Mode-UI/Nuklear.git
$ cd Nuklear/src

$ awk '                                                                                                                                                                                                                              
function buf_reset() { buf = "" }                                                                                                                                                                                                                              
function buf_append() { buf = buf "\n" FILENAME ":" FNR ":" $0 }                                                                                                                                                                                               
BEGIN { buf_reset() }                                                                                                                                                                                                                                          
/ *NK_ASSERT(.*);/ { buf_append(); next; }                                                                                                                                                                                                                     
/ *if(.*) return;/ { if (buf) { buf_append(); print buf; buf_reset(); } next; }                                                                                                                                                                                
/.*/ { buf_reset(); next; }                                                                                                                                                                                                                                    
' ./*.c

./nuklear_buffer.c:38:    NK_ASSERT(b);
./nuklear_buffer.c:39:    NK_ASSERT(a);
./nuklear_buffer.c:40:    NK_ASSERT(initial_size);
./nuklear_buffer.c:41:    if (!b || !a || !initial_size) return;

./nuklear_buffer.c:54:    NK_ASSERT(b);
./nuklear_buffer.c:55:    NK_ASSERT(m);
./nuklear_buffer.c:56:    NK_ASSERT(size);
./nuklear_buffer.c:57:    if (!b || !m || !size) return;

./nuklear_buffer.c:196:    NK_ASSERT(buffer);
./nuklear_buffer.c:197:    if (!buffer) return;

./nuklear_buffer.c:206:    NK_ASSERT(buffer);
./nuklear_buffer.c:207:    if (!buffer) return;

./nuklear_buffer.c:227:    NK_ASSERT(b);
./nuklear_buffer.c:228:    if (!b) return;

./nuklear_buffer.c:237:    NK_ASSERT(b);
./nuklear_buffer.c:238:    if (!b || !b->memory.ptr) return;

./nuklear_buffer.c:247:    NK_ASSERT(b);
./nuklear_buffer.c:248:    NK_ASSERT(s);
./nuklear_buffer.c:249:    if (!s || !b) return;

./nuklear_button.c:415:    NK_ASSERT(ctx);
./nuklear_button.c:416:    if (!ctx) return;

./nuklear_chart.c:90:    NK_ASSERT(ctx);
./nuklear_chart.c:91:    NK_ASSERT(ctx->current);
./nuklear_chart.c:92:    NK_ASSERT(ctx->current->layout);
./nuklear_chart.c:93:    NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
./nuklear_chart.c:94:    if (!ctx || !ctx->current || !ctx->current->layout) return;

./nuklear_chart.c:293:    NK_ASSERT(ctx);
./nuklear_chart.c:294:    NK_ASSERT(values);
./nuklear_chart.c:295:    if (!ctx || !values || !count) return;

./nuklear_chart.c:318:    NK_ASSERT(ctx);
./nuklear_chart.c:319:    NK_ASSERT(value_getter);
./nuklear_chart.c:320:    if (!ctx || !value_getter || !count) return;

./nuklear_context.c:12:    NK_ASSERT(ctx);
./nuklear_context.c:13:    if (!ctx) return;

./nuklear_context.c:90:    NK_ASSERT(ctx);
./nuklear_context.c:91:    if (!ctx) return;

./nuklear_context.c:178:    NK_ASSERT(ctx);
./nuklear_context.c:179:    NK_ASSERT(buffer);
./nuklear_context.c:180:    if (!ctx || !buffer) return;

./nuklear_context.c:197:    NK_ASSERT(ctx);
./nuklear_context.c:198:    NK_ASSERT(win);
./nuklear_context.c:199:    if (!ctx || !win) return;

./nuklear_context.c:213:    NK_ASSERT(ctx);
./nuklear_context.c:214:    NK_ASSERT(win);
./nuklear_context.c:215:    if (!ctx || !win) return;

./nuklear_context.c:224:    NK_ASSERT(ctx);
./nuklear_context.c:225:    NK_ASSERT(buffer);
./nuklear_context.c:226:    if (!ctx || !buffer) return;

./nuklear_context.c:236:    NK_ASSERT(ctx);
./nuklear_context.c:237:    NK_ASSERT(win);
./nuklear_context.c:238:    if (!ctx || !win) return;

./nuklear_contextual.c:183:    NK_ASSERT(ctx);
./nuklear_contextual.c:184:    NK_ASSERT(ctx->current);
./nuklear_contextual.c:185:    NK_ASSERT(ctx->current->layout);
./nuklear_contextual.c:186:    if (!ctx || !ctx->current || !ctx->current->layout) return;

./nuklear_contextual.c:194:    NK_ASSERT(ctx);
./nuklear_contextual.c:195:    NK_ASSERT(ctx->current);
./nuklear_contextual.c:196:    if (!ctx || !ctx->current) return;

./nuklear_draw.c:13:    NK_ASSERT(cb);
./nuklear_draw.c:14:    NK_ASSERT(b);
./nuklear_draw.c:15:    if (!cb || !b) return;

./nuklear_draw.c:25:    NK_ASSERT(b);
./nuklear_draw.c:26:    if (!b) return;

./nuklear_draw.c:72:    NK_ASSERT(b);
./nuklear_draw.c:73:    if (!b) return;

./nuklear_draw.c:93:    NK_ASSERT(b);
./nuklear_draw.c:94:    if (!b || line_thickness <= 0) return;

./nuklear_draw.c:111:    NK_ASSERT(b);
./nuklear_draw.c:112:    if (!b || col.a == 0 || line_thickness <= 0) return;

./nuklear_draw.c:133:    NK_ASSERT(b);
./nuklear_draw.c:134:    if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;

./nuklear_draw.c:156:    NK_ASSERT(b);
./nuklear_draw.c:157:    if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;

./nuklear_draw.c:180:    NK_ASSERT(b);
./nuklear_draw.c:181:    if (!b || rect.w == 0 || rect.h == 0) return;

./nuklear_draw.c:226:    NK_ASSERT(b);
./nuklear_draw.c:227:    if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;

./nuklear_draw.c:265:    NK_ASSERT(b);
./nuklear_draw.c:266:    if (!b || c.a == 0) return;

./nuklear_draw.c:282:    NK_ASSERT(b);
./nuklear_draw.c:283:    if (!b || c.a == 0 || line_thickness <= 0) return;

./nuklear_draw.c:309:    NK_ASSERT(b);
./nuklear_draw.c:310:    if (!b || c.a == 0) return;

./nuklear_draw.c:339:    NK_ASSERT(b);
./nuklear_draw.c:340:    if (!b || col.a == 0 || line_thickness <= 0) return;

./nuklear_draw.c:360:    NK_ASSERT(b);
./nuklear_draw.c:361:    if (!b || col.a == 0) return;

./nuklear_draw.c:381:    NK_ASSERT(b);
./nuklear_draw.c:382:    if (!b || col.a == 0 || line_thickness <= 0) return;

./nuklear_draw.c:399:    NK_ASSERT(b);
./nuklear_draw.c:400:    if (!b) return;

./nuklear_draw.c:499:    NK_ASSERT(b);
./nuklear_draw.c:500:    if (!b) return;

./nuklear_draw.c:525:    NK_ASSERT(b);
./nuklear_draw.c:526:    NK_ASSERT(font);
./nuklear_draw.c:527:    if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;

./nuklear_edit.c:78:    NK_ASSERT(out);
./nuklear_edit.c:79:    NK_ASSERT(font);
./nuklear_edit.c:80:    NK_ASSERT(style);
./nuklear_edit.c:81:    if (!text || !byte_len || !out || !style) return;

./nuklear_edit.c:684:    NK_ASSERT(ctx);
./nuklear_edit.c:685:    NK_ASSERT(ctx->current);
./nuklear_edit.c:686:    if (!ctx || !ctx->current) return;

./nuklear_edit.c:699:    NK_ASSERT(ctx);
./nuklear_edit.c:700:    NK_ASSERT(ctx->current);
./nuklear_edit.c:701:    if (!ctx || !ctx->current) return;

./nuklear_font.c:429:    NK_ASSERT(out_memory);
./nuklear_font.c:430:    NK_ASSERT(in_memory);
./nuklear_font.c:431:    NK_ASSERT(img_width);
./nuklear_font.c:432:    NK_ASSERT(img_height);
./nuklear_font.c:433:    if (!out_memory || !in_memory || !img_height || !img_width) return;

./nuklear_font.c:727:    NK_ASSERT (nk__dout + length <= nk__barrier);
./nuklear_font.c:728:    if (nk__dout + length > nk__barrier) { nk__dout += length; return; }

./nuklear_font.c:735:    NK_ASSERT (nk__dout + length <= nk__barrier);
./nuklear_font.c:736:    if (nk__dout + length > nk__barrier) { nk__dout += length; return; }

./nuklear_font.c:884:    NK_ASSERT(atlas);
./nuklear_font.c:885:    if (!atlas) return;

./nuklear_font.c:898:    NK_ASSERT(atlas);
./nuklear_font.c:899:    NK_ASSERT(alloc);
./nuklear_font.c:900:    if (!atlas || !alloc) return;

./nuklear_font.c:909:    NK_ASSERT(atlas);
./nuklear_font.c:910:    NK_ASSERT(permanent);
./nuklear_font.c:911:    NK_ASSERT(temporary);
./nuklear_font.c:912:    if (!atlas || !permanent || !temporary) return;

./nuklear_font.c:1314:    NK_ASSERT(atlas);
./nuklear_font.c:1315:    NK_ASSERT(atlas->temporary.alloc);
./nuklear_font.c:1316:    NK_ASSERT(atlas->temporary.free);
./nuklear_font.c:1317:    NK_ASSERT(atlas->permanent.alloc);
./nuklear_font.c:1318:    NK_ASSERT(atlas->permanent.free);
./nuklear_font.c:1319:    if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;

./nuklear_font.c:1336:    NK_ASSERT(atlas);
./nuklear_font.c:1337:    NK_ASSERT(atlas->temporary.alloc);
./nuklear_font.c:1338:    NK_ASSERT(atlas->temporary.free);
./nuklear_font.c:1339:    NK_ASSERT(atlas->permanent.alloc);
./nuklear_font.c:1340:    NK_ASSERT(atlas->permanent.free);
./nuklear_font.c:1341:    if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;

./nuklear_group.c:194:        NK_ASSERT(x_offset_ptr);
./nuklear_group.c:195:        NK_ASSERT(y_offset_ptr);
./nuklear_group.c:196:        if (!x_offset_ptr || !y_offset_ptr) return;

./nuklear_group.c:229:        NK_ASSERT(x_offset_ptr);
./nuklear_group.c:230:        NK_ASSERT(y_offset_ptr);
./nuklear_group.c:231:        if (!x_offset_ptr || !y_offset_ptr) return;

./nuklear_image.c:115:    NK_ASSERT(ctx);
./nuklear_image.c:116:    NK_ASSERT(ctx->current);
./nuklear_image.c:117:    NK_ASSERT(ctx->current->layout);
./nuklear_image.c:118:    if (!ctx || !ctx->current || !ctx->current->layout) return;

./nuklear_image.c:130:    NK_ASSERT(ctx);
./nuklear_image.c:131:    NK_ASSERT(ctx->current);
./nuklear_image.c:132:    NK_ASSERT(ctx->current->layout);
./nuklear_image.c:133:    if (!ctx || !ctx->current || !ctx->current->layout) return;

./nuklear_input.c:14:    NK_ASSERT(ctx);
./nuklear_input.c:15:    if (!ctx) return;

./nuklear_input.c:33:    NK_ASSERT(ctx);
./nuklear_input.c:34:    if (!ctx) return;

./nuklear_input.c:48:    NK_ASSERT(ctx);
./nuklear_input.c:49:    if (!ctx) return;

./nuklear_input.c:60:    NK_ASSERT(ctx);
./nuklear_input.c:61:    if (!ctx) return;

./nuklear_input.c:76:    NK_ASSERT(ctx);
./nuklear_input.c:77:    if (!ctx) return;

./nuklear_input.c:101:    NK_ASSERT(ctx);
./nuklear_input.c:102:    if (!ctx) return;

./nuklear_input.c:113:    NK_ASSERT(ctx);
./nuklear_input.c:114:    if (!ctx) return;

./nuklear_input.c:128:    NK_ASSERT(ctx);
./nuklear_input.c:129:    if (!ctx) return;

./nuklear_input.c:137:    NK_ASSERT(ctx);
./nuklear_input.c:138:    if (!ctx) return;

./nuklear_layout.c:308:    NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
./nuklear_layout.c:309:    NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
./nuklear_layout.c:310:    if (layout->row.type != NK_LAYOUT_TEMPLATE) return;

./nuklear_layout.c:328:    NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
./nuklear_layout.c:329:    NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
./nuklear_layout.c:330:    if (layout->row.type != NK_LAYOUT_TEMPLATE) return;

./nuklear_layout.c:348:    NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
./nuklear_layout.c:349:    NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
./nuklear_layout.c:350:    if (layout->row.type != NK_LAYOUT_TEMPLATE) return;

./nuklear_layout.c:375:    NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
./nuklear_layout.c:376:    if (layout->row.type != NK_LAYOUT_TEMPLATE) return;

./nuklear_list_view.c:70:    NK_ASSERT(view);
./nuklear_list_view.c:71:    NK_ASSERT(view->ctx);
./nuklear_list_view.c:72:    NK_ASSERT(view->scroll_pointer);
./nuklear_list_view.c:73:    if (!view || !view->ctx) return;

./nuklear_pool.c:37:    NK_ASSERT(size >= sizeof(struct nk_page));
./nuklear_pool.c:38:    if (size < sizeof(struct nk_page)) return;

./nuklear_popup.c:192:    NK_ASSERT(ctx);
./nuklear_popup.c:193:    if (!ctx || !ctx->current) return;

./nuklear_string.c:244:    NK_ASSERT(s);
./nuklear_string.c:245:    NK_ASSERT(len >= 0);
./nuklear_string.c:246:    if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;

./nuklear_string.c:259:    NK_ASSERT(str);
./nuklear_string.c:260:    NK_ASSERT(len >= 0);
./nuklear_string.c:261:    if (!str || len < 0) return;

./nuklear_style.c:112:    NK_ASSERT(ctx);
./nuklear_style.c:113:    if (!ctx) return;

./nuklear_style.c:847:    NK_ASSERT(ctx);
./nuklear_style.c:848:    if (!ctx) return;

./nuklear_style.c:857:    NK_ASSERT(ctx);
./nuklear_style.c:858:    if (!ctx) return;

./nuklear_text.c:17:    NK_ASSERT(o);
./nuklear_text.c:18:    NK_ASSERT(t);
./nuklear_text.c:19:    if (!o || !t) return;

./nuklear_text.c:67:    NK_ASSERT(o);
./nuklear_text.c:68:    NK_ASSERT(t);
./nuklear_text.c:69:    if (!o || !t) return;

./nuklear_text.c:104:    NK_ASSERT(ctx);
./nuklear_text.c:105:    NK_ASSERT(ctx->current);
./nuklear_text.c:106:    NK_ASSERT(ctx->current->layout);
./nuklear_text.c:107:    if (!ctx || !ctx->current || !ctx->current->layout) return;

./nuklear_text.c:131:    NK_ASSERT(ctx);
./nuklear_text.c:132:    NK_ASSERT(ctx->current);
./nuklear_text.c:133:    NK_ASSERT(ctx->current->layout);
./nuklear_text.c:134:    if (!ctx || !ctx->current || !ctx->current->layout) return;

./nuklear_text.c:260:    NK_ASSERT(ctx);
./nuklear_text.c:261:    if (!ctx) return;

./nuklear_text.c:267:    NK_ASSERT(ctx);
./nuklear_text.c:268:    if (!ctx) return;

./nuklear_text_editor.c:374:    NK_ASSERT(state);
./nuklear_text_editor.c:375:    NK_ASSERT(text);
./nuklear_text_editor.c:376:    if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;

./nuklear_text_editor.c:997:    NK_ASSERT(state);
./nuklear_text_editor.c:998:    NK_ASSERT(memory);
./nuklear_text_editor.c:999:    if (!state || !memory || !size) return;

./nuklear_text_editor.c:1007:    NK_ASSERT(state);
./nuklear_text_editor.c:1008:    NK_ASSERT(alloc);
./nuklear_text_editor.c:1009:    if (!state || !alloc) return;

./nuklear_text_editor.c:1018:    NK_ASSERT(state);
./nuklear_text_editor.c:1019:    if (!state) return;

./nuklear_text_editor.c:1035:    NK_ASSERT(state);
./nuklear_text_editor.c:1036:    if (!state) return;

./nuklear_tooltip.c:51:    NK_ASSERT(ctx);
./nuklear_tooltip.c:52:    NK_ASSERT(ctx->current);
./nuklear_tooltip.c:53:    if (!ctx || !ctx->current) return;

./nuklear_vertex.c:14:    NK_ASSERT(list);
./nuklear_vertex.c:15:    if (!list) return;

./nuklear_vertex.c:177:    NK_ASSERT(list);
./nuklear_vertex.c:178:    if (!list) return;

./nuklear_vertex.c:191:    NK_ASSERT(list);
./nuklear_vertex.c:192:    if (!list) return;

./nuklear_vertex.c:273:    NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
./nuklear_vertex.c:274:    NK_ASSERT(format <= NK_FORMAT_COLOR_END);
./nuklear_vertex.c:275:    if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;

./nuklear_vertex.c:349:    NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
./nuklear_vertex.c:350:    if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;

./nuklear_vertex.c:424:    NK_ASSERT(list);
./nuklear_vertex.c:425:    if (!list || points_count < 2) return;

./nuklear_vertex.c:665:    NK_ASSERT(list);
./nuklear_vertex.c:666:    if (!list || points_count < 3) return;

./nuklear_vertex.c:782:    NK_ASSERT(list);
./nuklear_vertex.c:783:    if (!list) return;

./nuklear_vertex.c:793:    NK_ASSERT(list);
./nuklear_vertex.c:794:    if (!list) return;

./nuklear_vertex.c:811:    NK_ASSERT(list);
./nuklear_vertex.c:812:    if (!list) return;

./nuklear_vertex.c:827:    NK_ASSERT(list);
./nuklear_vertex.c:828:    if (!list) return;

./nuklear_vertex.c:872:    NK_ASSERT(list);
./nuklear_vertex.c:873:    if (!list) return;

./nuklear_vertex.c:898:    NK_ASSERT(list);
./nuklear_vertex.c:899:    NK_ASSERT(list->path_count);
./nuklear_vertex.c:900:    if (!list || !list->path_count) return;

./nuklear_vertex.c:921:    NK_ASSERT(list);
./nuklear_vertex.c:922:    if (!list) return;

./nuklear_vertex.c:932:    NK_ASSERT(list);
./nuklear_vertex.c:933:    if (!list) return;

./nuklear_vertex.c:943:    NK_ASSERT(list);
./nuklear_vertex.c:944:    if (!list || !col.a) return;

./nuklear_vertex.c:958:    NK_ASSERT(list);
./nuklear_vertex.c:959:    if (!list || !col.a) return;

./nuklear_vertex.c:973:    NK_ASSERT(list);
./nuklear_vertex.c:974:    if (!list || !col.a) return;

./nuklear_vertex.c:999:    NK_ASSERT(list);
./nuklear_vertex.c:1000:    if (!list) return;

./nuklear_vertex.c:1021:    NK_ASSERT(list);
./nuklear_vertex.c:1022:    if (!list || !col.a) return;

./nuklear_vertex.c:1032:    NK_ASSERT(list);
./nuklear_vertex.c:1033:    if (!list || !col.a) return;

./nuklear_vertex.c:1044:    NK_ASSERT(list);
./nuklear_vertex.c:1045:    if (!list || !col.a) return;

./nuklear_vertex.c:1055:    NK_ASSERT(list);
./nuklear_vertex.c:1056:    if (!list || !col.a) return;

./nuklear_vertex.c:1066:    NK_ASSERT(list);
./nuklear_vertex.c:1067:    if (!list || !col.a) return;

./nuklear_vertex.c:1086:    NK_ASSERT(list);
./nuklear_vertex.c:1087:    if (!list) return;

./nuklear_vertex.c:1113:    NK_ASSERT(list);
./nuklear_vertex.c:1114:    if (!list) return;

./nuklear_vertex.c:1143:    NK_ASSERT(list);
./nuklear_vertex.c:1144:    if (!list || !len || !text) return;

./nuklear_window.c:66:    NK_ASSERT(ctx);
./nuklear_window.c:67:    NK_ASSERT(win);
./nuklear_window.c:68:    if (!win || !ctx) return;

./nuklear_window.c:72:        NK_ASSERT(iter != iter->next);
./nuklear_window.c:73:        NK_ASSERT(iter != win);
./nuklear_window.c:74:        if (iter == win) return;

./nuklear_window.c:552:    NK_ASSERT(ctx);
./nuklear_window.c:553:    if (!ctx) return;

./nuklear_window.c:556:    NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
./nuklear_window.c:557:    if (ctx->current == win) return;

./nuklear_window.c:566:    NK_ASSERT(ctx);
./nuklear_window.c:567:    if (!ctx) return;

./nuklear_window.c:609:    NK_ASSERT(ctx);
./nuklear_window.c:610:    if (!ctx) return;

./nuklear_window.c:624:    NK_ASSERT(ctx);
./nuklear_window.c:625:    if (!ctx || !cond) return;

./nuklear_window.c:634:    NK_ASSERT(ctx);
./nuklear_window.c:635:    if (!ctx) return;

./nuklear_window.c:649:    NK_ASSERT(ctx);
./nuklear_window.c:650:    if (!ctx || !cond) return;

./nuklear_window.c:660:    NK_ASSERT(ctx);
./nuklear_window.c:661:    if (!ctx) return;

sleeptightAnsiC avatar Oct 08 '25 14:10 sleeptightAnsiC

if a code works just fine with a null check, why does it need to be guarded with assert?

The answer is that assert macro is no-op in release builds, so it won't trigger on those.

lockie avatar Oct 10 '25 10:10 lockie

The answer is that assert macro is no-op in release builds, so it won't trigger on those.

That's what I thought, but wouldn't it make more sense to have something like this guarded with macro, like so:

#if !defined(NK_CHECK)
#define NK_CHECK(cond) \
    NK_ASSERT(cond); \
    if (cond); \
    else
#endif

...and then pattern would change to:

NK_CHECK(foo) return;
NK_CHECK(bar) return;

...and it would be possible to turn this macro into no-op with:

#define NK_CHECK(cond) \
    if (1); \
    else

Note that my biggest problem with current approach is:

(a) there are functions that I would expect to take NULL, e.g. any destructor, but those crash due to assert failing [...] For example nk_font_atlas_clear should work when passing NULL or empty atlas, but the assert causes an unexpected crash https://github.com/Immediate-Mode-UI/Nuklear/pull/779#discussion_r2331856071

...and this can be fixed without changing the "assert+nullcheck" pattern itself, but it's quite confusing when dealing with this kind of issues.

sleeptightAnsiC avatar Oct 10 '25 10:10 sleeptightAnsiC

Also (d) there are few places where NK_ASSERT(foo); has no corresponding if (!foo) return; (and vice versa), and it's hard to tell whether this is intentional or not.

sleeptightAnsiC avatar Oct 10 '25 10:10 sleeptightAnsiC