Search code examples
c++openglassets

Assets path : absolute vs generated


I'm currently making a "fromAssets" function that provide a path to the assets folder where ever the program is execute.

The function come from the following part of code.

Header file :

#include <iostream>
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

namespace path {
    static fs::path BUILD_PATH;
    const void initialiseBuildPath(const char *argv);
    const char * fromAssets(const char * path);
}

Source file :

using namespace path;

const void path::initialiseBuildPath(const char *argv0) {
    BUILD_PATH = fs::initial_path<fs::path>();
    BUILD_PATH = fs::system_complete(fs::path(argv0))
                            .parent_path()
                            .parent_path();
}

const char * path::fromAssets(const char * path) {
    std::string strPath = std::string(path);
    return (BUILD_PATH.string() + "/assets/" + strPath).c_str();
}

Use :

const char * absolute = "/Users/thomaspetillot/CLionProjects/glDiscoverProject/build/assets/shader/basic.vert.glsl";
const char * generated = path::fromAssets("shader/basic.vert.glsl");
cout << strcmp(absolute, generated) << endl; // show 0



// Work
auto * shader = new Shader(absolute,
                           path::fromAssets("shader/basic.frag.glsl"));

// Doesn't work
auto * shader = new Shader(generated,
                           path::fromAssets("shader/basic.frag.glsl"));

Folder structure :

build
├── assets
│   ├── img
│   │   ├── pepe.jpg
│   │   └── snoop.jpg
│   └── shader
│       ├── basic.frag.glsl
│       └── basic.vert.glsl
└── bin
    └── program

How can it work for the frag shader but not for the other ?


Solution

  • The fromAssets method returns a pointer to an invalid memory address. That happens because you return the c_str() pointer of a std::string object that is a local variable of that function. When the function returns, all local variables, including the std::string, get deleted and the pointer returned points to a no longer existing memory address.

    The best (and most modern) fix would be to return the std::string object itself instead of a const char* pointer. You can than either pass the c_str pointer to the Shader constructor or even better adjust the constructor to take const std::string& as parameters.