Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:

jobs:
test:
name: ${{ matrix.os }} / ${{ matrix.cc }} / C${{ matrix.std }}
name: ${{ matrix.os }} / ${{ matrix.cc }} / C${{ matrix.std }}${{ matrix.sanitize && ' / sanitizers' || '' }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand All @@ -17,6 +17,7 @@ jobs:
- { os: ubuntu-latest, cc: gcc, std: 23 }
- { os: macos-latest, cc: clang, std: 17 }
- { os: macos-latest, cc: gcc-14, std: 17 }
- { os: ubuntu-latest, cc: clang, std: 17, sanitize: ON }
env:
CC: ${{ matrix.cc }}
steps:
Expand All @@ -25,7 +26,7 @@ jobs:
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y flex bison
- name: Configure
run: cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_STANDARD=${{ matrix.std }} -DCMAKE_C_FLAGS=-Werror
run: cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_STANDARD=${{ matrix.std }} -DCMAKE_C_FLAGS=-Werror -DKC_SANITIZE=${{ matrix.sanitize || 'OFF' }}
- name: Build
run: cmake --build build -j4
- name: Test
Expand All @@ -34,5 +35,5 @@ jobs:
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-work-${{ matrix.os }}-${{ matrix.cc }}-c${{ matrix.std }}
name: test-work-${{ matrix.os }}-${{ matrix.cc }}-c${{ matrix.std }}${{ matrix.sanitize && '-sanitize' || '' }}
path: build/test-work
27 changes: 27 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ current C compilers, and an automated test suite has been added.
depend on the compiler or CPU.
* Legacy material (retired generators, DOS copies, platform Makefiles,
site-specific scripts) has been removed. It remains in git history.
* Expression trees are immutable and allocated from an arena: every
operation returns a new tree that shares its arguments instead of
copying them. This removes the memory leaks of the old copying API
and shrinks `symbmath.c` by about 600 lines. The generated code is
unchanged.
* The CMake option `KC_SANITIZE` builds kc with AddressSanitizer and
UndefinedBehaviorSanitizer.

### Tests

Expand All @@ -29,6 +36,10 @@ current C compilers, and an automated test suite has been added.
mode 3 simulations. Models that kc must reject are tested too.
* GitHub Actions runs the suite on Linux (GCC, clang, C23) and macOS
(clang, GCC 14).
One more Linux job runs it with sanitizers.
* New test models cover the derivatives of all functions
(`derivatives1`, `derivatives2`) and second and third derivatives by
dynamical variables in mode 5 (`hessian`).

### Changed results

Expand All @@ -37,6 +48,11 @@ current C compilers, and an automated test suite has been added.
reported a failure in `hqr2`, and D3 printed all-zero eigenvectors.
The eigenvector output (mostly normalization and sign) changes for
16 models.
* Reducing `f+(-g)` and `f-(-g)` kept the negation, so the sign of `g`
flipped every time the expression was reduced. Single Jacobian
entries of gtf and shn90 had the wrong value, which changes their
mode 1 eigenvalues and mode 3 end states. In other models only the
printed form changes, e.g. `x+(-(y))` is now `x-y`.

### Bug fixes

Expand Down Expand Up @@ -64,3 +80,14 @@ current C compilers, and an automated test suite has been added.
result of `TreeEval` and table lookups of unknown names.
* The warning for an unknown command-line option printed the wrong
character.
* Derivatives of functions: ln gave 0, tan and tanh gave `u'/(u*2)`,
asinh gave `u'`, acosh was not implemented and acos crashed kc.
* `asinh`, `acosh` and `atanh` of constants evaluated to their
argument.
* Mode 2: the initial values in `in.dat` were shifted by one species;
the first one was read out of bounds.
* Mode 5: second and third derivatives by dynamical variables were
stored in the wrong slot, which made kc crash on models with two
parameters and a dynamical variable. The `djacobian` procedure
assigned the wrong variables, with a division by zero in models
without constraints.
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ add_executable(kc
target_include_directories(kc PRIVATE src ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(kc PRIVATE kcsolvers)

# Developer option: check kc itself for memory errors, leaks and undefined
# behaviour. Only kc is instrumented, so generated simulators link as usual.
option(KC_SANITIZE "Build kc with AddressSanitizer and UndefinedBehaviorSanitizer" OFF)
if(KC_SANITIZE)
set(sanitize -fsanitize=address,undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer)
target_compile_options(kc PRIVATE ${sanitize})
target_link_options(kc PRIVATE ${sanitize})
endif()

configure_file(kci.in ${CMAKE_CURRENT_BINARY_DIR}/kci @ONLY)

install(TARGETS kc kcsolvers)
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,15 @@ compared as well, so error handling is tested too.
intended change of the output, rewrite the expected files with
`KC_UPDATE=1 ctest --test-dir build` and review the diff.

To check kc for memory errors, leaks and undefined behaviour, build it with
sanitizers (leaks are only detected on Linux):

```sh
cmake -B build-sanitize -DKC_SANITIZE=ON
cmake --build build-sanitize
ctest --test-dir build-sanitize -j8
```

## Legal issues

The program is copyrighted in the sense of GNU General Public License
Expand Down
1 change: 0 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ following list shows with which priority different subject should be
done:

* Better reduction of expressions.
* Better memory allocation (especially in `symbmath.{c,h}`).
* Better documentation, both user's and programmer's manual.
* Reorganise the table manager.
* Rewrite the grammar, i.e. better error recovery and many more consistency checks.
Expand Down
Loading
Loading