我遇到了一个我无法识别的特定内存泄漏问题。记忆的演出。
在这种特殊情况下,所有对象都在堆栈中(尽管大多数对象都在堆上创建)。对象非常短暂,并且在大多数情况下,生活在循环中。我不确切知道发生了什么,但他们积累的尸体留在记忆中。我做了足够的调试,以确定它们的创建(以及随后从内存中删除的失败)是导致内存浪费的原因。
通过相当多的测试,我已经验证了构造函数被调用的次数等于析构函数被调用的次数。其中一个类是一个虚拟类,所以我确保它的析构函数是虚拟的(它是)。 Valgrind并未指出任何内存泄漏。我不知道还有什么可以尝试的。我几乎以为我遇到了编译器错误,但通常这意味着我错了。
如果有人可以帮助我,我会非常感激!
以下是我正在使用的基本课程。我用它们在C ++中重新创建了一个生成器的概念。它们几乎是我整个计划的关键所在:
/**
* @file generator.hpp
* @brief Macros and class to create generators
*
* @author Adam Baxter
* @version 2.0
* @date 2012/07/11
* @copyright 2012
*/
#ifndef apollo_generator_hpp_
#define apollo_generator_hpp_
/**
* @brief A macro to define the beginning of a generator's operator() function
*/
#define $gen_start if(_line < 0) { _line = 0;} \
switch(_line) { case 0:;
/**
* @brief A macro to define the end of a generator's operator() function
*/
#define $gen_stop } _line = 0; return false;
/**
* @brief A macro to yield the generator's current position and create that corrosponding return value
*/
#define $yield(R) \
do { \
_line = __LINE__; \
generate(R); return true; case __LINE__:; \
} while (0);
namespace apollo {
/**
* @class Generator generator.hpp "generator.hpp"
* @brief Standard generator interface for all generators in this project.
The macros above, coupled with this class, are used to define functions that can be jumped into and out at arbitrary positions
Consider NumGen, a simple number generator:
class NumGen : public Generator<int> {
NumGen() : _i(0), Generator<int>() {}
bool operator()(value_type &rv) {
$gen_start;
for(_i = 0; _i < 10; _i++) {
$yield(rv);
}
$gen_stop;
}
void generate(value_type &rv) {
rv = _i;
}
private:
value_type _i;
};
NumGen is nothing more than a simple for-loop that yields numbers [0,10).
The importance of the generator is to separate out the generator's next state calculation (_i++)
from the return value's generator (rv = _i) from the rest of the application logic
The more complex of a state we're working with, the more powerful this idea becomes.
@Note Successive calls to operator() will place execution directly after
the last called yield statement
- Any variable modification between $gen_start and $yield will be skipped! -
A generator's state must be held in its member variables and care must be exercised when using
local variables in operator().
*/
template <typename T>
class Generator {
public:
/**
* The type the generator creates
*/
typedef T value_type;
// default ctor
Generator(): _line(-1) {}
// copy ctor
Generator(Generator const &rhs) : _line(rhs._line) {}
// move ctor
Generator(Generator &&rhs) : _line(rhs._line) {}
// copy = ctor
Generator& operator=(Generator const &rhs)
{
if (this != &rhs) {
_line = rhs._line;
}
return *this;
}
// move = ctor
Generator& operator=(Generator &&rhs)
{
if (this != &rhs) {
_line = rhs._line;
}
return *this;
}
/**
* Generator calculates its next state, creates the value for that state.
*
* @param[in,out] rv The return value's storage location
*
* @return True if generator at next state and a new return value is generated.
* False if there are no more valid states and return value is untouched.
*/
virtual bool operator()(value_type &rv) = 0;
/**
* Using the generator's current state, create the return value
*
* @param[in,out] rv The return value's storage location
*/
virtual void generate(value_type &rv) const = 0;
// == operator
virtual bool operator==(Generator const &rhs) const {
return _line == rhs._line;
}
// deconstructor
virtual ~Generator() {}
protected:
int _line; /**< The source code line $gen_start will use for its switch */
};
} /* namespace apollo */
#endif // apollo_generator_hpp_
和
/**
* @file generatoriterator.hpp
* @brief A class to create iterators out of generators
*
* @author Adam Baxter
* @version 2.0
* @date 2012/07/11
* @copyright 2012
*/
#ifndef apollo_generatoriterator_hpp_
#define apollo_generatoriterator_hpp_
#include <utility>
#include <iterator>
#include <boost/iterator/iterator_facade.hpp>
namespace apollo {
template <typename G>
class GeneratorIterator : public boost::iterator_facade <
GeneratorIterator<G>,
const typename G::value_type,
boost::forward_traversal_tag> {
public:
typedef G generator_t;
GeneratorIterator() : _finished(true) {}
explicit GeneratorIterator(generator_t const &gen) :
_gen(gen),
_finished(false) {
this->operator++();
}
explicit GeneratorIterator(generator_t &&gen) :
_gen(std::forward<generator_t>(gen)),
_finished(false) {
this->operator++();
}
GeneratorIterator(GeneratorIterator const &rhs) :
_gen(rhs._gen),
_finished(rhs._finished) {
if (!_finished) {
_gen.generate(_rv);
}
}
GeneratorIterator(GeneratorIterator &&rhs) :
_gen(std::move(rhs._gen)),
_rv(std::move(rhs._rv)),
_finished(rhs._finished) {}
GeneratorIterator& operator=(GeneratorIterator const &rhs) {
if (this != &rhs) {
_gen = rhs._gen;
_finished = rhs._finished;
if (!_finished) {
_gen.generate(_rv);
}
}
return *this;
}
GeneratorIterator& operator=(GeneratorIterator &&rhs) {
if (this != &rhs) {
_gen = std::move(rhs._gen);
_rv = std::move(rhs._rv);
_finished = rhs._finished;
}
return *this;
}
generator_t const& gen() const {
return _gen;
}
~GeneratorIterator() {}
private:
friend class boost::iterator_core_access;
generator_t _gen;
typename generator_t::value_type _rv;
bool _finished;
bool equal(GeneratorIterator const &rhs) const {
if (_finished || rhs._finished) {
if (_finished && rhs._finished) {
return true;
} else {
return false;
}
} else if ((_rv == rhs._rv) &&
(_gen == rhs._gen)) {
return true;
}
return false;
}
void increment() { advance(); }
void advance(std::ptrdiff_t dist = 1) {
while (!_finished && (dist > 0)) {
if( _gen(_rv) == false) {
_finished = true;
}
dist -= 1;
}
}
std::ptrdiff_t distance_to(GeneratorIterator const &rhs) const {
using std::distance;
if (_finished && rhs._finished) {
return 0;
}
if (!_finished) {
return distance(*this, rhs);
} else {
return distance(rhs, *this) * -1;
}
}
const typename generator_t::value_type& dereference() const { return _rv; }
};
template<class G, typename... Args>
GeneratorIterator<G> make_geniter(Args && ...args) {
return GeneratorIterator<G>(G(std::forward<Args>(args)...));
}
} /* namespace apollo */
#endif /* apollo_generatoriterator_hpp_ */
答案 0 :(得分:4)
我已经知道发生了什么。内存问题是由于我仍然在Boost :: flat_map和朋友中追踪的bug,其中flat_map.insert(iterator,iterator)导致内存泄漏。但是,我没有认出它,因为我称之为flatmap(const&amp; flatmap)。我想它仍然做同样的事情。