以下代码在指示的地方断言"迭代器+偏移量超出范围。"
void Network::PushInput(int c, int h, int w) {
Input* input = new Input(batch, c, h, w, data);
layers.push_back(input); // this happens to be the first push_back()
// layers.push_back(input); // doing another doesn't change the assert!
Layer *foo = layers.back(); // asserts here
Layer *baz = layers[layers.size()-1]; // does not assert
}
Input是Layer的公共子类。图层声明为
std::vector<Layer *>layers;
如果我尝试使用更多的vanilla模板类型复制上面的内容,例如int *,则back()按预期工作,没有断言。不知何故,模板类型在这里很重要。 (注意:_ITERATOR_DEBUG_LEVEL为2,触发向量类中的断言检查。)
我不是直截了当地将代码中的所有back()更改为size() - 1,而是宁愿了解这里发生了什么。
有什么想法吗? (我将继续扰乱代码,直到找到明显的原因,但希望这对其他人来说是显而易见的。)
(我使用Visual Studio 2013社区版,如果重要的话。)
.....
这是一个独立的文件,可以编译显示问题:
#include <vector>
using namespace std;
namespace layer {
class Layer {
public:
Layer(float alpha = 0, float momentum = 0.9f, float weight_decay = 0);
virtual ~Layer();
// three virtual method that all layers should have
virtual void forward(bool train = true) = 0;
virtual void backward() = 0;
virtual void update() = 0;
void adjust_learning(float scale); // change the learning rate
Layer* prev; // previous layer
Layer* next; // next layer
float* data; // X': output (cuDNN y)
int batch; // n: batch size
float alpha; // learning rate
float momentum; // beta: momentum of gradient
float weight_decay; // gamma: weight decay rate
};
} /* namespace layer */
namespace layer {
Layer::Layer(float alpha_, float momentum_, float weight_decay_)
{
std::memset(this, 0, sizeof(*this));
alpha = alpha_;
momentum = momentum_;
weight_decay = weight_decay_;
}
Layer::~Layer() {}
void Layer::adjust_learning(float scale) {
alpha *= scale;
}
}
namespace layer {
class Input : public Layer {
public:
Input(int n, int c, int h, int w, float* _data);
virtual ~Input();
void forward(bool train = true);
void backward();
void update();
};
}
namespace layer {
Input::Input(int n, int c, int h, int w, float* _data) : Layer() {
prev = NULL;
batch = n;
data = _data;
}
Input::~Input() {
data = NULL;
}
void Input::forward(bool train) {
// nothing
}
void Input::backward() {
// nothing
}
void Input::update() {
// nothing
}
}
using namespace layer;
namespace model {
class Network {
private:
std::vector<Layer*> layers; // list of layers
bool has_input, has_output; // sanity check
float* data; // input on device
int batch; // whole size of data, batch size
public:
Network(int batch_size);
virtual ~Network();
void PushInput(int c, int h, int w);
};
}
namespace model {
void Network::PushInput(int c, int h, int w) {
Input* input = new Input(batch, c, h, w, data);
layers.push_back(input);
Layer *foo = layers.back(); // **WHY DOES THIS ASSERT??**
}
Network::Network(int _batch) {
std::memset(this, 0, sizeof(*this));
batch = _batch;
}
Network::~Network() {
for (Layer* l : layers)
delete l;
}
}
void main()
{
model::Network foo(10);
foo.PushInput(2, 3, 4);
}
答案 0 :(得分:4)
您的代码中有未定义的行为。
在Layer
构造函数中执行
std::memset(this, 0, sizeof(*this));
这个问题是上面的调用也会清除虚函数表(它是对象的一部分)。之后调用的任何虚函数都将无法正常工作(如果有的话)。这包括破坏对象,因为析构函数是虚拟的。