'memory leak when loading and unloading textures

Does anyone know why there is a memory leak when loading and unloading textures to memory? Memory leak asserts under specific conditions

I have a texture class. The code is below: Texture.h

#pragma once

#include <string>
#include <vector>
#include "../../vendor/headers/stb_image.h"

class Texture {
    friend class BatchRenderer;
    // Object
    private:
        unsigned int textureID, textureSlot;
        unsigned char* image;
        int width, height, bpp;
    public:
        Texture(const std::string& path); // To-Do: Replace "const std::string& path" with a char array. "const std::string& path" is alive for the lifetime of the program.
        Texture(const char* path);

        unsigned int getTextureID() const;
        int getTextureSlot() const;
        unsigned int getWidth() const;
        unsigned int getHeight() const;
        unsigned int getBPP() const;

        ~Texture();
};

Texture.cpp

#include "Texture.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>

// To-Do: Replace "const std::string& path" with a char array. "const std::string& path" is alive for the lifetime of the program.
Texture::Texture(const std::string& path) : textureID(0), image(nullptr), width(0), height(0), bpp(0) {
    stbi_set_flip_vertically_on_load(1);
    image = stbi_load(path.c_str(), &width, &height, &bpp, 4);

    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
    glBindTexture(GL_TEXTURE_2D, 0);

    textureSlot = 0;
}

Texture::Texture(const char* path) {
    stbi_set_flip_vertically_on_load(1);
    image = stbi_load(path, &width, &height, &bpp, 4);

    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
    glBindTexture(GL_TEXTURE_2D, 0);

    textureSlot = 0;
}

unsigned int Texture::getTextureID() const {
    return textureID;
}

int Texture::getTextureSlot() const {
    return textureSlot;
}

unsigned int Texture::getWidth() const {
    return width;
}

unsigned int Texture::getHeight() const {
    return height;
}

unsigned int Texture::getBPP() const {
    return bpp;
}

Texture::~Texture() {
    if (image)
        stbi_image_free(image);
    glDeleteTextures(1, &textureID);
}

Main.cpp

#include <iostream>
#include "batchrenderer/classes/Texture.h"

using namespace std;

int main() {
    cout << "Program operating..." << endl;

    string pause;
    
    cout << "Enter anything to continue: ";
    cin >> pause;

    for (unsigned int i = 0; i < 1000; i++) {
        Texture* texture = new Texture("C:\\Users\\chris\\source\\repos\\BatchRenderer\\BatchRenderer\\resources\\coloredsquares\\black.png");
        delete(texture);
    }
    cout << "Enter anything to continue: ";
    cin >> pause;
    for (unsigned int i = 0; i < 1000; i++) {
        Texture* texture = new Texture("C:\\Users\\chris\\source\\repos\\BatchRenderer\\BatchRenderer\\resources\\coloredsquares\\black.png");
        delete(texture);
    }
    cout << "Enter anything to continue: ";
    cin >> pause;
    for (unsigned int i = 0; i < 1000; i++) {
        Texture* texture = new Texture("C:\\Users\\chris\\source\\repos\\BatchRenderer\\BatchRenderer\\resources\\coloredsquares\\black.png");
        delete(texture);
    }

    cout << "Enter anything to continue: ";
    cin >> pause;

    cout << "Program terminated..." << endl;
}

Here is what my diagnostics tool looks like. I am not sure if there is a small bug in the VS code and there is actually no memory leak or if there is a memory leak and it is something SO small that I cannot pin point it. When the code is profiled with a loop of 100 times, there is no leak. The memory leak only asserts when the loop exceeds 1000 loops. Does anyone know anything about why this is happening. Note: there appear to be no memory leak when only 1 texture is load. Or maybe there is, but it is negligible until you have created a LOT of Texture objects. enter image description here

Note: I was suspecting it was the string object but did not find anything when I profiled that specific thing. Unless I profiled it wrong.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source