为什么我得到'矢量下标超出范围'?

nam*_*ame 0 c++ opengl

我正在尝试做最简单的事情,但我得到一个'矢量下标超出范围'的错误!我不明白为什么,因为我检查确保不会发生.它出现的唯一功能是addTexture一个.

TextureBank.h

#pragma once
#include "Disposable.h"
#include "Texture.h"
#include <vector>

class TextureBank: public Disposable
{
public:
    TextureBank();
    ~TextureBank();

    virtual void dispose();

    void addTexture(int location, Texture *tex);
    Texture *getTexture(int location);
private:
    std::vector<Texture*> textures;
};
Run Code Online (Sandbox Code Playgroud)

TextureBank.cpp

#include "TextureBank.h"


TextureBank::TextureBank()
{
}

void TextureBank::dispose() {
    for each (Texture* tex in textures)
    {
        if (tex != nullptr) {
            tex->dispose();
        }
    }
}

void TextureBank::addTexture(int location, Texture *tex) {
    if (location > textures.size() - 1) {
        textures.resize(location + 1, nullptr);
    }
    textures[location] = tex;
}

Texture *TextureBank::getTexture(int location) {
    return textures[location];
}

TextureBank::~TextureBank()
{
    for each (Texture* tex in textures)
    {
        if (tex != nullptr) {
            delete tex;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Pra*_*ian 5

罪魁祸首很可能就是这句话:

if (location > textures.size() - 1) {
Run Code Online (Sandbox Code Playgroud)

textures.size()将是一个无符号整数类型,并且location是一个int.在大于比较之前,将应用通常的算术转换,这意味着location将转换为相同的无符号整数类型.

如果textures为空且location为零,textures.size() - 1则将导致该无符号类型的最大值,并且比较将产生false.textures将不会调整大小,并且您将尝试访问空的第0个元素vector,从而导致异常.

您可以通过将其修改为轻松修复条件

if (location >= textures.size()) {
Run Code Online (Sandbox Code Playgroud)

location如果不能为负,也可以考虑制作无符号类型; 并打开编译器的警告级别并注意警告!


您还应该考虑进行一些其他更改:

  • for each (Texture* tex in textures)是一些非标准的编译器扩展.for如果可能的话,你应该用一个范围替换它-for(auto tex : textures)

  • 而不是存储原始拥有指针textures,考虑将类型更改为std::vector<std::unique_ptr<Texture>>.然后,您将不必delete在析构函数中显式地显示每个纹理.

  • 如果您不能使用unique_ptr,请确保您的班级遵循三法则.

  • Dispose()您最好不要使用函数等来创建小型RAII包装器来处理需要内存管理的OpenGL类型.