# Windows native build with ASan - Claude AI notes: ASan found a heap-use-after-free bug

**URL:** <https://swi-prolog.discourse.group/t/windows-native-build-with-asan-claude-ai-notes-asan-found-a-heap-use-after-free-bug/9500>\
**Category:** Help!\
**Created:** [January 29, 2026, 9:31am UTC](https://swi-prolog.discourse.group/t/windows-native-build-with-asan-claude-ai-notes-asan-found-a-heap-use-after-free-bug/9500 "2026-01-29T09:31:31Z")\
**Posts on this page:** 1\
**Showing post:** 52

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [February 7, 2026, 12:47pm UTC](https://swi-prolog.discourse.group/t/windows-native-build-with-asan-claude-ai-notes-asan-found-a-heap-use-after-free-bug/9500/52 "2026-02-07T12:47:45Z")

</div>

Thinking out loud here so @jan, @peter.ludemann and @mgondan1 can see this and possibly comment.

The builds for the tests discussed below are done using **MSVC + CMake** , **Debug** , with **ASan enabled**..

**Note:** I am not entirely sure the following interpretation is correct. I have been trying to confirm details in Microsoft documentation, but searching for **`%ERRORLEVEL%`** has not been very helpful.

On Windows, **`%ERRORLEVEL%`** is used to propagate process exit codes (see Microsoft’s documentation on [system error codes](https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-)).

It appears that some tests do **not** check the value of **`%ERRORLEVEL%`** when running on Windows. As a result, tests may report as _passed_ while still returning a non-zero exit code, which can lead to invalid or unexpected results.

This may be happening in the following case.

```c++
PREDICATE(call_cpp_ex, 2)
{ try
  { PlCheckFail(PlCall(A1, PL_Q_CATCH_EXCEPTION));
  } catch ( PlException& ex )
  { bool rc = A2.unify_term(ex.term());
    Plx_clear_exception();
    return rc;
  }
  return A2.unify_string("no exception");
}

```

Corresponding test

```prolog
test(call_cpp_06,nondet) :-
    call_cpp_ex(unknown_pred(hello(世界四)), Ex),
    assertion(subsumes_term(error(existence_error(procedure, unknown_pred/1), _), Ex)).

```

When this test is run _by itself_, it reports success: `passed (0.031 sec CPU)`

However, checking **`%ERRORLEVEL%`** afterward shows that the return value is **1** , not **0** :

```prolog
C:\dev-MSVC-PR\swipl-devel\build>"C:\dev-MSVC-PR\swipl-devel\build\src\Debug\swipl.exe" -p "foreign=" -f none --no-packs --on-error=status -s "C:/dev-MSVC-PR/swipl-devel/packages/cpp/test_cpp.pl" -g "run_tests(cpp:call_cpp_06)" -t halt
% Start unit: cpp
% [1/1] cpp:call_cpp_06 .................................................................................................................................... passed (0.035 sec)
% test passed

C:\dev-MSVC-PR\swipl-devel\build>echo %ERRORLEVEL%
1

```

For comparison, similar tests _do_ return `0` as expected:

```prolog
test(call_cpp_05, Ex == "no exception") :-
    call_cpp_ex(writeln(hello(世界四)), Ex).

```

```prolog
C:\dev-MSVC-PR\swipl-devel\build>"C:\dev-MSVC-PR\swipl-devel\build\src\Debug\swipl.exe" -p "foreign=" -f none --no-packs --on-error=status -s "C:/dev-MSVC-PR/swipl-devel/packages/cpp/test_cpp.pl" -g "run_tests(cpp:call_cpp_05)" -t halt  
% Start unit: cpp
% [1/1] cpp:call_cpp_05 ..hello(世界四)
............................................................................................................................................................ passed (0.039 sec)
% End unit cpp: passed (0.047 sec CPU)
% test passed in 0.114 seconds (0.125 cpu)

C:\dev-MSVC-PR\swipl-devel\build>echo %ERRORLEVEL%                                                                                                                                     
0

```

```prolog
test(call_cpp_03, error(existence_error(procedure,unknown_pred/1))) :-
    call_cpp(unknown_pred(hello(世界四))).

```

```prolog
C:\dev-MSVC-PR\swipl-devel\build>"C:\dev-MSVC-PR\swipl-devel\build\src\Debug\swipl.exe" -p "foreign=" -f none --no-packs --on-error=status -s "C:/dev-MSVC-PR/swipl-devel/packages/cpp/test_cpp.pl" -g "run_tests(cpp:call_cpp_03)" -t halt
% Start unit: cpp
% [1/1] cpp:call_cpp_03 .................................................................................................................................... passed (0.039 sec)        
% End unit cpp: passed (0.031 sec CPU)
% test passed in 0.108 seconds (0.094 cpu)

C:\dev-MSVC-PR\swipl-devel\build>echo %ERRORLEVEL%
0

```

* * *

### What led me to this

When `call_cpp_06` is **blocked** , the output looks correct and test numbering proceeds as expected:

```prolog
% [13/247] cpp:call_cpp_04 ..................................................................................................................... passed (0.000 sec)
% [14/247] cpp:call_cpp_05 ..hello(世界四)
................................................................................................................................................ passed (0.001 sec)        
% [15/247] cpp:call_cpp_09 ..................................................................................................................... passed (0.000 sec)        
% [16/247] cpp:as_string_01 .................................................................................................................... passed (0.000 sec)  

```

(`call_cpp_07` and `call_cpp_08` are also blocked.)

However, when `call_cpp_06` is **unblocked** , the output changes in an unexpected way:

```prolog
% [13/248] cpp:call_cpp_04 ................................................................................................................................. passed (0.000 sec)        
% [14/248] cpp:call_cpp_05 ..hello(世界四)
............................................................................................................................................................ passed (0.000 sec)        
% [15/248] cpp:call_cpp_06 ................................................................................................................................. passed (0.000 sec)        
% 5 tests are blocked (use run_tests/2 with show_blocked(true) for details)
% All 248 (+-233 sub-tests) tests passed

```

What I would expect instead is for the output to continue with the remaining tests, for example:

```prolog
% [16/248] cpp:call_cpp_09 ..................................................................................................................... passed (0.000 sec)        
% [17/248] cpp:as_string_01 .................................................................................................................... passed (0.000 sec) 

```

…and then the rest of the test suite.

---

_[View the full topic](https://swi-prolog.discourse.group/t/windows-native-build-with-asan-claude-ai-notes-asan-found-a-heap-use-after-free-bug/9500)._
