Is there a problem with using textures I drew in Paint?

As the title says, I’m trying to render a cube using the code below (plus a custom Shader class and the actual shaders omitted for brevity) to render a tilted cube turning on the Y axis.

The problem is with the texture: if I just download some .png from Google Images it renders just fine, but if I create some random texture using MS Paint and only change the file path to said MS Paint texture I get an Exception thrown at 0x00007FFA3BEADB68 (nvoglv64.dll) in Untitled_OpenGL_Project.exe: 0xC0000005: Access violation reading location 0x000001F6A94A2000. exception.

What is the problem? Is it something to do with the value for transparent pixels or something? (grasping at straws here)

main.cpp:

#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "Shader.h"
#include "utils.h"
#include "stb_image.h"

int main()
{
    // Setup 
    if (!Utility::glfwSetup())
        return -1;

    GLFWwindow* window = Utility::glfwOpenWindow(Utility::SCREEN_WIDTH, Utility::SCREEN_HEIGHT, "GLFW Window");
    glfwMakeContextCurrent(window);

    if (!Utility::gladSetup())
        return -1;

    glfwSetKeyCallback(window, Utility::key_callback);
    glEnable(GL_DEPTH_TEST);

    // Program
    glViewport(0, 0, 800, 600);

    float vertices[] = {
        // Position          // Texel
        -0.5f, -0.5f,  0.5f, 0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f, 0.0f, 1.0f,
         0.5f, -0.5f,  0.5f, 1.0f, 0.0f,
         0.5f,  0.5f,  0.5f, 1.0f, 1.0f,

        -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f, 0.0f, 1.0f,
         0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
         0.5f,  0.5f, -0.5f, 1.0f, 1.0f,

         0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
         0.5f,  0.5f, -0.5f, 0.0f, 1.0f,
         0.5f, -0.5f,  0.5f, 1.0f, 0.0f,
         0.5f,  0.5f,  0.5f, 1.0f, 1.0f,

        -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f, 0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f, 1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f, 1.0f, 1.0f,

        -0.5f,  0.5f, -0.5f, 0.0f, 0.0f,
         0.5f,  0.5f, -0.5f, 0.0f, 1.0f,
        -0.5f,  0.5f,  0.5f, 1.0f, 0.0f,
         0.5f,  0.5f,  0.5f, 1.0f, 1.0f,

        -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
         0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f, 1.0f, 0.0f,
         0.5f, -0.5f,  0.5f, 1.0f, 1.0f
    };  
    unsigned int indices[] = {  
         0,  1,  3,
         0,  2,  3,

         4,  5,  7,
         4,  6,  7,

         8,  9, 11,
         8, 10, 11,

        12, 13, 15,
        12, 14, 15,

        16, 17, 19,
        16, 18, 19,

        20, 21, 23,
        20, 22, 23
    };

    // Buffer setup
    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    unsigned int EBO;
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    unsigned int VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    float tiltAngle = 70.0f;

    // MVP
    glm::mat4 model = glm::mat4(1.0f);
    glm::vec3 zAxis = glm::vec3(0.0f, 0.0f, 1.0f);
    model = glm::rotate(model, (float) glm::radians(tiltAngle), zAxis);
    glm::mat4 view = glm::mat4(1.0f);
    view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
    glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float) Utility::SCREEN_WIDTH / Utility::SCREEN_HEIGHT, 0.1f, 100.0f);

    // Texture
    unsigned int texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    Utility::texSetup(GL_REPEAT, GL_REPEAT, GL_NEAREST, GL_LINEAR);

    int width, height, numChannels;
    unsigned char* data = stbi_load("res/textures/BlackFrame.png", &width, &height, &numChannels, 0);
    if (data)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data);

    // Shader setup
    Shader shader("res/shaders/VertexShader.shader", "res/shaders/FragShader.shader");
    glUseProgram(shader.ID);
    shader.setUniformMat4f(model, "model");
    shader.setUniformMat4f(view, "view");
    shader.setUniformMat4f(proj, "proj");
    shader.setUniform1i(0, "texture1");

    // Time
    float prevTime = (float)glfwGetTime();

    while (!glfwWindowShouldClose(window))
    {
        // Setup
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Input
        Utility::processInput(window);

        // Rendering
        float curTime = (float)glfwGetTime();
        float deltaTime = curTime - prevTime;
        prevTime = curTime;

        // Rotate around Y axis
        glm::vec3 yAxis = glm::vec3(0.0f, 1.0f, 0.0f);
        model = glm::rotate(model, (float)glm::radians(-tiltAngle), zAxis);
        model = glm::rotate(model, deltaTime, yAxis);
        model = glm::rotate(model, (float)glm::radians(tiltAngle), zAxis);
        shader.setUniformMat4f(model, "model");

        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

        // Clean-up
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

utils.cpp:

int Utility::glfwSetup()
{
    if (!glfwInit())
    {
        std::cerr << "Failed to initialize GLFW" << std::endl;
        return 0;
    }
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, VERSION_MAJOR);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, VERSION_MINOR);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    std::cout << "GLFW " << VERSION_MAJOR << "." << VERSION_MINOR << " initialized successfully." << std::endl;

    return 1;
}

int Utility::gladSetup()
{
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        glfwTerminate();
        return 0;
    }

    return 1;
}

void Utility::texSetup(int wrapParamS, int wrapParamT, int minParam, int magParam)
{
    stbi_set_flip_vertically_on_load(true);

    float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapParamS);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapParamT);
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minParam);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magParam);
}

GLFWwindow* Utility::glfwOpenWindow(int width, int height, const char* title)
{
    GLFWwindow* window = glfwCreateWindow(width, height, title, NULL, NULL);
    if (window == NULL)
    {
        std::cerr << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return NULL;
    }

    return window;
}

void Utility::processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GLFW_TRUE);
}

Answer

It is not guaranteed that a PNG file has 4 channels or that stbi_load will return an image with 4 channels.

stbi_load can be forced to generate an image with 4 color channels, by explicitly pass 4 to the last parameter:

unsigned char* data = stbi_load("BlackFrame.png", &width, &height, &numChannels, 0);

unsigned char* data = stbi_load("BlackFrame.png", &width, &height, &numChannels, 4);

See stb_image.h:

Basic usage (see HDR discussion below for HDR usage):
     int x,y,n;
     unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
     // ... process data if not NULL ...
     // ... x = width, y = height, n = # 8-bit components per pixel ...
     // ... replace '0' with '1'..'4' to force that many components per pixel
     // ... but 'n' will always be the number that it would have been if you said 0
     stbi_image_free(data);