std::vector back()的奇怪行为
Odd behavior of std::vector back()
以下代码在所示位置断言"迭代器+偏移量超出范围。"
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;
如果我试图用更多的普通模板类型来复制上面的内容,例如,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);
}
您的代码中有未定义的行为。
在Layer
构造函数中执行
std::memset(this, 0, sizeof(*this));
问题是,上面的调用也会清除虚拟函数表(它是对象的一部分)。之后调用的任何虚拟函数都将无法按预期工作(如果有的话)。这包括销毁对象,因为销毁程序是虚拟的。
相关文章:
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中用vector填充一个简单的动态数组
- vector.resize()中的分配错误
- 使用std::vector的OpenCL矩阵乘法
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 在某些循环内使用vector.push_back时出现分段错误
- 当vector是tje全局变量时,c++中vector的内存管理
- std::vector的包装器,使数组的结构看起来像结构的数组
- 为什么(-1)%vector::size()总是返回0
- 推导 std::vector::back() 的返回类型
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- vector.push_back(vector.back()+1) 是未定义的行为吗?
- std::vector using back(), pop_back(), push_back(), 得到'double free or corruption'错误
- vector.back()和vector.end()有什么区别
- vector.back() 可以用来为向量的最后一个元素赋值吗?
- 在std::vector中实现back()
- std::vector back()的奇怪行为
- 修改向量后引用 vector.back() 的奇怪行为
- std::vector::back 和 vector::operator[ vector::size() - 1] 之间
- 为什么对std::vector::back()的调用会使我的程序崩溃