diff --git a/configure.ac b/configure.ac index 5d99a6d41..ceceb9d40 100644 --- a/configure.ac +++ b/configure.ac @@ -141,7 +141,7 @@ fi AX_CHECK_BUDDY -AC_CHECK_HEADERS([sys/times.h]) +AC_CHECK_HEADERS([sys/times.h valgrind/memcheck.h]) AC_CHECK_FUNCS([times kill alarm sigaction]) LT_CONFIG_LTDL_DIR([ltdl]) diff --git a/spot/misc/fixpool.hh b/spot/misc/fixpool.hh index 81c4393db..691f31c75 100644 --- a/spot/misc/fixpool.hh +++ b/spot/misc/fixpool.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2011, 2015, 2016 Laboratoire de Recherche et +// Copyright (C) 2011, 2015, 2016, 2018 Laboratoire de Recherche et // Développement de l'Epita (LRDE) // // This file is part of Spot, a model checking library. @@ -20,9 +20,10 @@ #pragma once #include -#include -#include -#include + +#if SPOT_DEBUG && defined(HAVE_VALGRIND_MEMCHECK_H) +#include +#endif namespace spot { @@ -60,6 +61,12 @@ namespace spot // If we have free blocks available, return the first one. if (f) { +#if SPOT_DEBUG && defined(HAVE_VALGRIND_MEMCHECK_H) + VALGRIND_MALLOCLIKE_BLOCK(f, size_, 0, false); + // field f->next is initialized: prevents valgrind from complaining + // about jumps depending on uninitialized memory + VALGRIND_MAKE_MEM_DEFINED(f, sizeof(block_*)); +#endif freelist_ = f->next; return f; } @@ -83,6 +90,9 @@ namespace spot void* res = free_start_; free_start_ += size_; +#if SPOT_DEBUG && defined(HAVE_VALGRIND_MEMCHECK_H) + VALGRIND_MALLOCLIKE_BLOCK(res, size_, 0, false); +#endif return res; } @@ -99,6 +109,9 @@ namespace spot block_* b = reinterpret_cast(const_cast(ptr)); b->next = freelist_; freelist_ = b; +#if SPOT_DEBUG && defined(HAVE_VALGRIND_MEMCHECK_H) + VALGRIND_FREELIKE_BLOCK(ptr, 0); +#endif } private: diff --git a/spot/misc/mspool.hh b/spot/misc/mspool.hh index eb827ff27..e83ff3cc2 100644 --- a/spot/misc/mspool.hh +++ b/spot/misc/mspool.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2011, 2013, 2015, 2016 Laboratoire de Recherche et +// Copyright (C) 2011, 2013, 2015, 2016, 2018 Laboratoire de Recherche et // Developpement de l'Epita (LRDE) // // This file is part of Spot, a model checking library. @@ -20,10 +20,11 @@ #pragma once #include -#include -#include -#include -#include +#include + +#if SPOT_DEBUG && defined(HAVE_VALGRIND_MEMCHECK_H) +#include +#endif namespace spot { @@ -69,6 +70,12 @@ namespace spot if (f) { block_* first = f; +#if SPOT_DEBUG && defined(HAVE_VALGRIND_MEMCHECK_H) + VALGRIND_MALLOCLIKE_BLOCK(f, size, 0, false); + // field f->next is initialized: prevents valgrind from complaining + // about jumps depending on uninitialized memory + VALGRIND_MAKE_MEM_DEFINED(f, sizeof(block_*)); +#endif f = f->next; return first; } @@ -92,6 +99,9 @@ namespace spot void* res = free_start_; free_start_ += size; +#if SPOT_DEBUG && defined(HAVE_VALGRIND_MEMCHECK_H) + VALGRIND_MALLOCLIKE_BLOCK(res, size, 0, false); +#endif return res; } @@ -113,6 +123,9 @@ namespace spot block_*& f = freelist_[size]; b->next = f; f = b; +#if SPOT_DEBUG && defined(HAVE_VALGRIND_MEMCHECK_H) + VALGRIND_FREELIKE_BLOCK(ptr, 0); +#endif } private: diff --git a/tests/Makefile.am b/tests/Makefile.am index 9c311b5ed..8d9a67fd1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -81,6 +81,7 @@ check_PROGRAMS = \ core/ltl2text \ core/ltlrel \ core/lunabbrev \ + core/mempool \ core/nequals \ core/nenoform \ core/ngraph \ @@ -112,6 +113,7 @@ core_ikwiad_SOURCES = core/ikwiad.cc core_intvcomp_SOURCES = core/intvcomp.cc core_intvcmp2_SOURCES = core/intvcmp2.cc core_kripkecat_SOURCES = core/kripkecat.cc +core_mempool_SOURCES = core/mempool.cc core_ngraph_SOURCES = core/ngraph.cc core_randtgba_SOURCES = core/randtgba.cc core_taatgba_SOURCES = core/taatgba.cc @@ -186,6 +188,7 @@ TESTS_tl = \ core/eventuniv.test \ core/stutter-ltl.test \ core/hierarchy.test \ + core/mempool.test \ core/format.test TESTS_graph = \ diff --git a/tests/core/.gitignore b/tests/core/.gitignore index bdea8cd42..254d5cee1 100644 --- a/tests/core/.gitignore +++ b/tests/core/.gitignore @@ -40,6 +40,7 @@ lunabbrev Makefile Makefile.in maskacc +mempool mixprod nequals nenoform diff --git a/tests/core/mempool.cc b/tests/core/mempool.cc new file mode 100644 index 000000000..19fd35951 --- /dev/null +++ b/tests/core/mempool.cc @@ -0,0 +1,160 @@ +// -*- coding: utf-8 -*- +// Copyright (C) 2016, 2018 Laboratoire de Recherche et Développement +// de l'Epita. +// +// This file is part of Spot, a model checking library. +// +// Spot is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// Spot is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "config.h" + +#define SPOT_DEBUG 1 + +#include +#include + +namespace +{ + struct boxint + { + int i; + }; + + class foo + { + boxint* b; + public: + foo(int i): b(new boxint{i}) {} + ~foo() { delete b; } + + void incr() { ++b->i; } + }; + + // use a fixpool for allocation + class bar + { + int i; + + static spot::fixed_size_pool& pool() + { + static spot::fixed_size_pool p{sizeof(bar)}; + return p; + } + + public: + bar(int i): i(i) {} + + static void* operator new(size_t) + { + return pool().allocate(); + } + static void operator delete(void* ptr) + { + pool().deallocate(ptr); + } + + void incr() { ++i; } + }; + + // use a mspool for allocation + class baz + { + int i; + + static spot::multiple_size_pool& pool() + { + static spot::multiple_size_pool p{}; + return p; + } + + public: + baz(int i): i(i) {} + + static void* operator new(size_t) + { + return pool().allocate(sizeof(baz)); + } + static void operator delete(void* ptr) + { + pool().deallocate(ptr, sizeof(baz)); + } + + void incr() { ++i; } + }; + + +} // anonymous namespace + + +int main() +{ + +#ifndef HAVE_VALGRIND_MEMCHECK_H + return 77; +#endif + + { + spot::fixed_size_pool p(sizeof(foo)); + + foo* a = new (p.allocate()) foo(1); + a->incr(); + // delete and deallocate, no problem + a->~foo(); + p.deallocate(a); + + a = new (p.allocate()) foo(2); + a->incr(); + // delete but do not deallocate: valgrind should find a leak + a->~foo(); + + a = new (p.allocate()) foo(3); + a->incr(); + // deallocate but do not delete: valgrind should find a leak + p.deallocate(a); + } + + { + spot::multiple_size_pool p; + + foo* a = new (p.allocate(sizeof(foo))) foo(1); + a->incr(); + // delete and deallocate, no problem + a->~foo(); + p.deallocate(a, sizeof(foo)); + + a = new (p.allocate(sizeof(foo))) foo(2); + a->incr(); + // delete but do not deallocate: valgrind should find a leak + a->~foo(); + + a = new (p.allocate(sizeof(foo))) foo(3); + a->incr(); + // deallocate but do not delete: valgrind should find a leak + p.deallocate(a, sizeof(foo)); + } + + { + bar* b = new bar(1); + b->incr(); + // no delete: valgrind should find a leak + } + { + baz* c = new baz(1); + c->incr(); + // no delete: valgrind should find a leak + } + + return 0; +} + diff --git a/tests/core/mempool.test b/tests/core/mempool.test new file mode 100644 index 000000000..59b3e61cc --- /dev/null +++ b/tests/core/mempool.test @@ -0,0 +1,34 @@ +#!/bin/sh +# -*- coding: utf-8 -*- +# Copyright (C) 2018 Laboratoire de Recherche et Développement de l'Epita. +# +# This file is part of Spot, a model checking library. +# +# Spot is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Spot is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +. ./defs + +set -e + +cat >exp < err + grep "ERROR SUMMARY" err | sed 's/^==[0-9]*==\s*//' > out + diff exp out +fi +