My program isn't allowing me to create fragment shader

Hi everyone, I was making a shader class header which loads the shader from files, compiles and links them into the final shader object. It’s based on this: https://learnopengl.com/code_viewer_gh.php?code=includes/learnopengl/shader_s.h

I remade it using the C way of reading files to read the files and it works perfectly fine when reading the file into the pointer. However, once I try to create a fragment shader like this:

GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

, it doesn’t allow me and says

Thread 1: EXC_BAD_ACCESS (code = 1, address = 0x1298)

I tried to use glGet Error to see if I could get the error code but the program crashes once it gets to the line with glCreateShader, so I can’t get the error code.

If I try to run the program, it results in a glitchy screen when you press q and then if the q button is pressed a second time, I get the screen filled with a green colour. I think this is happening because the shader isn’t working, although even when I did it without the shader class and just wrote out the shader as a pointer and compiled/linked it without wrapping it in a class*, it still gave me glitchy output.
*The shader did compile and link that time, so I don’t understand why it’s glitching.


#ifndef shader_h
#define shader_h

#include <iostream>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#include <stdlib.h>

class Shader{
public:
    Shader(const char * vshaderFile, const char * fshaderFile); // parameters are:
    // path to vertex shader, path to fragment shader.
    //geometry shader to be added later.
    
    ~Shader();
    void Use() { glUseProgram (this->shaderProgram); }
    
private:
    GLuint shaderProgram;
};

Shader::Shader(const char * vshaderFile, const char * fshaderFile){
    
    //read vertex shader
    long length;
    char * vertexBuf;
    FILE * vertexFile = fopen(vshaderFile, "r");
    
    if(!vertexFile) { std::cout << "Could not open vertex shader" << std::endl; }
    fseek(vertexFile, 0, SEEK_END);
    length = ftell(vertexFile);
    
    vertexBuf = new char [length + 1];
    fseek(vertexFile, 0, SEEK_SET);
    fread(vertexBuf, length, 1, vertexFile);
    fclose(vertexFile);
    vertexBuf[length] = 0; //makes the terminating character null
    
    //read fragment shader
    long length2;
    char * fragmentBuf;
    FILE * fragmentFile = fopen(fshaderFile, "r");
    
    if(!fragmentFile){ std::cout << "Could not open fragment shader" << std::endl; }
    fseek(fragmentFile, 0, SEEK_END);
    length2 = ftell(fragmentFile);
    
    fragmentBuf = new char [length2 + 1];
    fseek(fragmentFile, 0, SEEK_SET);
    fread(fragmentBuf, length2, 1, fragmentFile);
    fclose(fragmentFile);
    fragmentBuf[length2] = 0;
    
    //makes the source pointers the buffers
    GLchar * vShaderSource = vertexBuf;
    GLchar * fShaderSource = fragmentBuf;
    
    GLuint vertexShader, fragmentShader;
    
    //compiles shaders
    
    //fragment
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //HERE is where it crashes. It reads the file just fine.
    //std::cout << glGetError() << std::endl;
    glShaderSource(fragmentShader, 1, &fShaderSource, NULL);
    glCompileShader(fragmentShader);
    
    //vertex
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vShaderSource, NULL);
    glCompileShader(vertexShader);
    
    //releases buffers
    delete fragmentBuf;
    delete vertexBuf;
    
    //links program
    this->shaderProgram = glCreateProgram();
    glAttachShader(this->shaderProgram, vertexShader);
    glAttachShader(this->shaderProgram, fragmentShader);
    
    glLinkProgram(this->shaderProgram);
    
    //deletes unneeded shaders
    glDeleteShader(fragmentShader);
    glDeleteShader(vertexShader);
};

Shader::~Shader(){
    glDeleteProgram(this->shaderProgram);
};

#endif /* shader_h */

and then


#include <iostream>
#include <SDL2/SDL.h>
#include "shader.hpp"
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>

SDL_GLContext context;
SDL_Window * window;

bool initWindow(){
    
    if (SDL_Init(SDL_INIT_VIDEO)<0){
        std::cout << "Can't make SDL" << std::endl;
    }
    
    //what version we are using
    SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    //SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
    
    window = SDL_CreateWindow("Rectangle", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 512, 512, SDL_WINDOW_OPENGL);
    if (!window){
        std::cout << "No window created" << std::endl;
        //window = NULL;
        return false;
    }
    
    context = SDL_GL_CreateContext(window);
    if (!context){
        std::cout << "No context created" << std::endl;
        return false;
    }
    
    //double buffering - 24bit z buffer (might need changing for different systems)
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    
    //Makes buffer swap sync with VBLANK
    SDL_GL_SetSwapInterval(1);
    
    glViewport(0, 0, 512, 512);
    
    std:: cout << "Initialised" << std::endl;
    
    return true;
};

int main(int argc, const char * argv[]) {
    
    Shader shader ("fragment.txt", "vertex.txt");
    
//This is copypasted from the tutorial
//until the event loop
    float vertices[] = {
        0.5f,  0.5f, 0.0f,  // top right
        0.5f, -0.5f, 0.0f,  // bottom right
        -0.5f, -0.5f, 0.0f,  // bottom left
        -0.5f,  0.5f, 0.0f   // top left
    };
    unsigned int indices[] = {  // note that we start from 0!
        0, 1, 3,  // first Triangle
        1, 2, 3   // second Triangle
    };
    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);
    // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
    glBindVertexArray(VAO);
    
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    
    // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    // remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
    // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
    // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
    glBindVertexArray(0);
    
    bool loop = true;
    
    while (loop) {
        SDL_Event e;
        while(SDL_PollEvent(&e)){
            if (e.type == SDL_QUIT) loop = false;
            if (e.type == SDL_KEYDOWN){
                switch(e.key.keysym.sym){
                    case SDLK_ESCAPE:
                        loop = false;
                        break;
                    case SDLK_q:
                        shader.Use();
                        glBindVertexArray(VAO);
                        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (GLfloat*)0);
                        glBindVertexArray(0);
                        SDL_GL_SwapWindow(window);
                        //std::cout << glCheckError() << std::endl;
                        break;
                    case SDLK_y:
                        std::cout << glGetString(GL_VERSION) << std::endl;
                        break;
                    case SDLK_r:
                        glClearColor(0.3f, 0.5f, 0.2f, 1.0f);
                        glClear(GL_COLOR_BUFFER_BIT);
                        break;
                }
                std::cout << "Error: " << SDL_GetError() << std::endl;
                std::cout << glGetError() << std::endl;
            }
        }
        
    }
    
}