GitHub Actionsilla voit automatisoida muistivuotojen tarkistamisen jokaisen push-tapahtuman yhteydessä.
Alla oleva työnkulku käyttää kahta eri työkalua: AddressSanitizeria (käännösaikainen tarkistus) ja Valgrindia (ajonaikainen analyysi).
Lisää projektiisi .github/workflows/-hakemisto ja luo sinne YAML-tiedosto seuraavalla sisällöllä.
myapplication on testattavan C++-sovelluksen nimi, joten korvaa se oman projektisi suoritettavan tiedoston nimellä. Huomaa, että GitHub buildaa sovelluksen Linux-koneessa, joten .exe-päätettä ei käytetä, vaikka sovelluksesi olisi tehty Windowsilla.
name: C++ Memory Checks
on:
push:
branches:
- memtest
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y g++ cmake valgrind
- name: Build project (with AddressSanitizer)
run: |
mkdir build-asan
cd build-asan
cmake -DCMAKE_CXX_FLAGS="-g -O1 -fsanitize=address,leak -fno-omit-frame-pointer" ..
make -j
- name: Run with AddressSanitizer
run: |
cd build-asan
ASAN_OPTIONS=detect_leaks=1 ./myapplication
- name: Build project (without sanitizers, for Valgrind)
run: |
mkdir build-valgrind
cd build-valgrind
cmake -DCMAKE_CXX_FLAGS="-g -O1" ..
make -j
- name: Run Valgrind memory check
run: |
cd build-valgrind
valgrind \
--leak-check=full \
--show-leak-kinds=all \
--track-origins=yes \
--error-exitcode=1 \
./myapplication
name: C++ Memory ChecksTämä määrittää workflow’n näkyvän nimen GitHubissa.
on:
push:
branches:
- memtest
Workflow käynnistyy ainoastaan kun memtest-haaraan tehdään push. Muut haarat eivät laukaise tätä workflowta.
jobs:
build-and-test:
runs-on: ubuntu-latest
Määrittelee yhden työn nimeltä build-and-test, joka ajetaan Ubuntulla. GitHub tarjoaa virtuaalikoneen ilmaiseksi julkisille repositoryille rajoituksetta, privaateille tietyin kuukausittaisin minuuttikiintiöin.
- name: Checkout repository
uses: actions/checkout@v4
Kloonaa repositoryn koodin virtuaalikoneelle. Tämä on lähes aina workflows-tiedoston ensimmäinen vaihe.
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y g++ cmake valgrind
Asentaa tarvittavat työkalut: C++-kääntäjän (g++), build-järjestelmän (cmake) sekä Valgrind-muistianalysaattorin.
- name: Build project (with AddressSanitizer)
run: |
mkdir build-asan
cd build-asan
cmake -DCMAKE_CXX_FLAGS="-g -O1 -fsanitize=address,leak -fno-omit-frame-pointer" ..
make -j
Kääntää projektin AddressSanitizer-lipuilla erilliseen build-asan-hakemistoon. Tärkeimmät liput:
-fsanitize=address,leak:aktivoi muistivuoto- ja osoitevirhetarkistukset-g:lisää debuggaustiedot, jotta virheilmoituksissa näkyy tiedostonimi ja rivinumero-fno-omit-frame-pointer:säilyttää pinojäljityksen luettavana - name: Run with AddressSanitizer
run: |
cd build-asan
ASAN_OPTIONS=detect_leaks=1 ./myapplication
Ajaa käännetyn ohjelman AddressSanizerin kanssa. muistivuoto on buildissa syntyvän suoritettavan tiedoston nimi: se määritellään projektin CMakeLists.txt-tiedostossa. ASAN_OPTIONS=detect_leaks=1 varmistaa, että myös muistivuodot raportoidaan eikä pelkästään virheelliset muistiviittaukset. Jos ohjelma vuotaa muistia, prosessi päättyy virheeseen ja workflow epäonnistuu.
- name: Build project (without sanitizers, for Valgrind)
run: |
mkdir build-valgrind
cd build-valgrind
cmake -DCMAKE_CXX_FLAGS="-g -O1" ..
make -j
Kääntää projektin uudelleen ilman sanitizer-lippuja erilliseen build-valgrind-hakemistoon. Valgrind ei toimi yhteen sanitizereiden kanssa, joten tarvitaan oma käännös.
- name: Run Valgrind memory check
run: |
cd build-valgrind
valgrind \
--leak-check=full \
--show-leak-kinds=all \
--track-origins=yes \
--error-exitcode=1 \
./myapplication
Ajaa ohjelman Valgrindin läpi. Käytetyt valitsimet:
--leak-check=full:raportoi jokaisen yksittäisen vuodon--show-leak-kinds=all:näyttää myös epäsuorat ja mahdolliset vuodot--track-origins=yes:kertoo mistä alustamaton muisti on peräisin--error-exitcode=1:palauttaa virhekoodin, jolloin workflow epäonnistuu automaattisesti jos vuotoja löytyy
Alla oleva workflow laajentaa muistitestauksen niin, että onnistuneiden testien jälkeen
sovelluksesta luodaan automaattisesti GitHub Release -julkaisu sekä Linuxille että Windowsille.
Workflow käynnistyy ainoastaan kun release-haara päivittyy.
myapplication on testattavan C++-sovelluksen nimi — korvaa se oman projektisi suoritettavan tiedoston nimellä.
name: Memory Check and Release
on:
push:
branches:
- release
permissions:
contents: write
jobs:
memory-check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y g++ cmake valgrind
- name: Build with AddressSanitizer
run: |
mkdir build-asan
cd build-asan
cmake -DCMAKE_CXX_FLAGS="-g -O1 -fsanitize=address,leak -fno-omit-frame-pointer" ..
make -j
- name: Run AddressSanitizer
run: |
cd build-asan
ASAN_OPTIONS=detect_leaks=1 ./myapplication
- name: Build for Valgrind
run: |
mkdir build-valgrind
cd build-valgrind
cmake -DCMAKE_CXX_FLAGS="-g -O1" ..
make -j
- name: Run Valgrind
run: |
cd build-valgrind
valgrind \
--leak-check=full \
--show-leak-kinds=all \
--track-origins=yes \
--error-exitcode=1 \
./myapplication
build-linux:
needs: memory-check
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y g++ cmake
- name: Build release
run: |
mkdir build-release
cd build-release
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j
- name: Upload Linux artifact
uses: actions/upload-artifact@v4
with:
name: myapplication-linux
path: build-release/myapplication
build-windows:
needs: memory-check
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install MinGW
run: choco install mingw -y
- name: Build release
run: |
mkdir build-release
cd build-release
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
- name: Upload Windows artifact
uses: actions/upload-artifact@v4
with:
name: myapplication-windows
path: build-release/myapplication.exe
create-release:
needs: [build-linux, build-windows]
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: build-${{ github.run_number }}
name: Release ${{ github.run_number }}
files: |
myapplication-linux/myapplication
myapplication-windows/myapplication.exe
on:
push:
branches:
- release
Workflow käynnistyy ainoastaan kun release-haaraan tehdään push. Muut haarat eivät laukaise tätä workflowta.
permissions: contents: writeAntaa workflowlle oikeuden luoda GitHub Release -julkaisuja repositoryyn. Ilman tätä release-vaihe epäonnistuu lupapuutteeseen.
Workflow koostuu neljästä työstä, jotka suoritetaan seuraavassa järjestyksessä:
memory-check: muistitestit (AddressSanitizer + Valgrind)build-linux ja build-windows: ajetaan rinnakkain vasta kun testit ovat läpäisseetcreate-release: luodaan julkaisu vasta kun molemmat buildit ovat valmiit build-linux:
needs: memory-check
build-windows:
needs: memory-check
needs määrittää riippuvuuden: nämä kaksi työtä käynnistyvät vain jos memory-check onnistui. Koska molemmat viittaavat samaan edeltäjään, GitHub ajaa ne rinnakkain — Windows- ja Linux-buildit tapahtuvat samanaikaisesti.
- name: Upload Linux artifact
uses: actions/upload-artifact@v4
with:
name: myapplication-linux
path: build-release/myapplication
Tallentaa käännetyn suoritettavan tiedoston väliaikaiseen GitHub-varastoon työnimen alle. Artifaktit ovat saatavilla muille töille saman workflow-ajon sisällä.
- name: Install MinGW
run: choco install mingw -y
- name: Build release
run: |
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
Windows-build ajetaan Windows-virtuaalikoneella, mutta MSVC-kääntäjän sijaan käytetään MinGW:tä. Syy: MSVC ei tunne unistd.h-headeria, joka on POSIX-standardin osa eikä kuulu Windowsin omaan C-kirjastoon. MinGW sisältää GCC-kääntäjän Windows-versiona ja tukee POSIX-headereita, joten koodi kääntyy muuttamatta. choco on Windowsin paketinhallinta, joka on valmiiksi asennettuna GitHub-virtuaalikoneissa. Suoritettava tiedosto syntyy suoraan build-release/myapplication.exe-polkuun.
create-release:
needs: [build-linux, build-windows]
Tämä työ odottaa, että molemmat build-työt ovat onnistuneet. Jos kumpi tahansa epäonnistuu, release jää luomatta.
- name: Download artifacts
uses: actions/download-artifact@v4
Lataa molemmat aiemmin tallennetut artifaktit. Ilman parametreja lataa kaikki saman ajon artifaktit omiin alikansioihinsa (myapplication-linux/ ja myapplication-windows/).
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: build-${{ github.run_number }}
name: Release ${{ github.run_number }}
files: |
myapplication-linux/myapplication
myapplication-windows/myapplication.exe
Luo GitHub Release -julkaisun ja liittää siihen molemmat binäärit ladattaviksi. github.run_number on automaattisesti kasvava juokseva numero (1, 2, 3, …), joka toimii releasen versiotunnisteena.