2

I recently passed my game engine to a memory leak test with valgrind; it actually told me that there are ~7000 bytes being leaked in my Mesh class; the strange thing is that is tells me this :

7,280 bytes in 1 blocks are definitely lost in loss record 391 of 393
==5639==    at 0x4C2C100: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5639==    by 0x598647E: ??? (in /usr/lib/libassimp.so.3.0.1264)
==5639==    by 0x597F37D: ??? (in /usr/lib/libassimp.so.3.0.1264)
==5639==    by 0x58139E5: ??? (in /usr/lib/libassimp.so.3.0.1264)
==5639==    by 0x581E2B2: Assimp::Importer::ReadFile(char const*, unsigned int) (in /usr/lib/libassimp.so.3.0.1264)
==5639==    by 0x40D71A: glDetail::CMesh::CMesh(char const*) (Mesh.cpp:49)
==5639==    by 0x412FB5: _ZN9__gnu_cxx13new_allocatorIN8glDetail5CMeshEE9constructIS2_IRPKcEEEvPT_DpOT0_ (in /home/mattmatt/workspace/C++/alpha++/main-dev/eclipse/Alpha++/Debug/Alpha++)

So Question is : is Assimp responsible for the leaked memory ? Here is the part of code which is in question :

CMesh::CMesh(const char* fileName){
    Assimp::Importer importer;

    const aiScene* scene = importer.ReadFile(fileName,  aiProcess_Triangulate |
                                                        aiProcess_GenSmoothNormals |
                                                        aiProcess_FlipUVs |
                                                        aiProcess_CalcTangentSpace
                                                        );
    if(!scene){
        LOG_ERROR("Mesh", "ERROR LOADING MESH ! : CHECK THE SUPPORTED MODEL TYPES MODEL I OR THE FILE PATH !");
        abort();
    }
    const aiMesh* model = scene->mMeshes[0];

    std::vector<Vertex> vertices;
    std::vector<unsigned int> indices;

    const aiVector3D aiZeroVector(.0f, .0f, .0f);
    IndexedModel out;

    for(unsigned i = 0; i < model->mNumVertices; ++i)
    {
        const aiVector3D* pPos = &(model->mVertices[i]);
        const aiVector3D* pNormal = &(model->mNormals[i]);
        const aiVector3D* pTexCoord = model->HasTextureCoords(0) ? &(model->mTextureCoords[0][i]) : &aiZeroVector;

        const aiVector3D* pTangent = &(model->mTangents[i]);

        Vertex vert (
                        glm::vec3(pPos->x, pPos->y, pPos->z),///positions
                        glm::vec2(pTexCoord->x, pTexCoord->y),///UV coords
                        glm::vec3(pNormal->x, pNormal->y, pNormal->z),///normals
                        glm::vec3(pTangent->x, pTangent->y, pTangent->z)///tangents

                    );

        vertices.push_back(vert);

        out.positions.push_back(*vert.getPos());
        out.texCoords.push_back(*vert.getTexCoord());
        out.normals.push_back(*vert.getNormal());
        out.tangents.push_back(*vert.getTangent());
    }
    for(unsigned i = 0; i < model->mNumFaces; ++i){
        const aiFace& face = model->mFaces[i];
        assert(face.mNumIndices == 3);
        indices.push_back(face.mIndices[0]);
        indices.push_back(face.mIndices[1]);
        indices.push_back(face.mIndices[2]);
    }


    importer.FreeScene();

    out.indices = indices;
    initMesh(out);
}

the full code for my mesh class can be viewed at this question Memory Leak in opengl Mesh class if necessary :)

////////////////////////////Important Edit///////////////////////////

I isolated the part of code which leaked resources :

Assimp::Importer importer;

       const aiScene* scene = importer.ReadFile("res/Suzy.obj",  aiProcess_Triangulate |
                                                           aiProcess_GenSmoothNormals |
                                                           aiProcess_FlipUVs |
                                                            aiProcess_CalcTangentSpace
                                                           );
       if(!scene){
           LOG_ERROR("Mesh", "ERROR LOADING MESH ! : CHECK THE SUPPORTED MODEL TYPES MODEL I OR THE FILE PATH !");
           abort();
       }

What do I have to change ?

Community
  • 1
  • 1
Coder32
  • 181
  • 1
  • 10
  • 1
    Don't use plain pointers. Use e.g. `unique_ptr` and the problem will solve itself. – Piotr Siupa Jul 29 '15 at 10:34
  • my library uses pointers, but then wraps everything as a shared_ptr to the user; what was the problem here though ? – Coder32 Jul 29 '15 at 10:43
  • [Documentation](http://assimp.sourceforge.net/lib_html/class_assimp_1_1_importer.html#a174418ab41d5b8bc51a044895cb991e5) of function`ReadFile` says "The returned data is intended to be read-only, the importer object keeps ownership of the data and will destroy it upon destruction." It looks like the code is correct. Perhaps it is a problem with valgrind. – Piotr Siupa Jul 29 '15 at 10:56
  • 1
    You could run the code multiple times and check if the program really takes more memory. – Piotr Siupa Jul 29 '15 at 10:59
  • 1
    I just read that post : http://stackoverflow.com/questions/1997171/why-does-valgrind-say-basic-sdl-program-is-leaking-memory ; I think that would be the answer to everything; it wasn't who was leaking -> it were the libs ! – Coder32 Jul 29 '15 at 11:03
  • 2) Runned it multiple times; same thing . – Coder32 Jul 29 '15 at 11:03
  • 2
    maybe you are missing a void Assimp::Importer::FreeScene call since it seems ReadFile allocates some memory and keeps it internally? – AndersK Jul 29 '15 at 11:07
  • @CyberSpock 1) He call `FreeScene`. 2) [Documantation](http://assimp.sourceforge.net/lib_html/class_assimp_1_1_importer.html#a53dafc3046abc33365a07c605716c5d4) says "FreeScene() is called automatically by the destructor and ReadFile() itself. " – Piotr Siupa Jul 29 '15 at 11:10
  • I don't like function `abort`. Do you really have a reason to use it? http://stackoverflow.com/questions/2820285/abort-terminate-or-exit – Piotr Siupa Jul 29 '15 at 11:17
  • 2
    It looks like you are using Fedora. The ??? lines mean that debugging information is not available. Try installing the [debuginfo package](http://fedoraproject.org/wiki/StackTraces#What_are_debuginfo_rpms.2C_and_how_do_I_get_them.3F) via: `sudo yum --enablerepo fedora-debuginfo,updates-debuginfo install assimp-debuginfo` And then re-run Valgrind. This should give you a more informative backtrace. – Daniel Trebbien Jul 29 '15 at 11:19
  • Nope; using Ubuntu 15.04 - – Coder32 Jul 29 '15 at 11:21

2 Answers2

1

I've experienced those errors too with SDL2 or opengl; You have to assume that the assimp devs know what they are doing; same thing for opengl, glew and SDL2.

0

The documentation of Importer::ReadFile(const char *, unsigned) states:

If the call succeeds, the contents of the file are returned as a pointer to an aiScene object. The returned data is intended to be read-only, the importer object keeps ownership of the data and will destroy it upon destruction.

Based on this, it would appear that you are using the Assimp library correctly, but there is a memory leak issue within the library itself.

The ??? lines mean that debugging information is not available. If this is indeed a true memory leak, it is immensely useful to have debugging information in order to determine exactly where the memory leak is occurring. Debugging information is especially important in this case because Importer::ReadFile() calls a non-virtual BaseImporter::ReadFile(const Importer*, const std::string&, IOSystem*) member, which then calls the pure-virtual BaseImporter::InternReadFile(const std::string&, aiScene*, IOSystem*) member. I would assume that 0x58139E5 is BaseImporter::ReadFile(). Stack frames beyond that would depend on which BaseImporter implementation was selected by Importer::ReadFile().

On Fedora systems, debugging information can be obtained by installing the corresponding debuginfo package when available. Fedora provides an assimp-debuginfo package that can be installed via:

sudo yum --enablerepo fedora-debuginfo,updates-debuginfo install assimp-debuginfo

On Ubuntu and Debian systems, debugging information is obtained by installing the -dbg package when available. Unfortunately, neither Debian 8 'Jessie' nor Ubuntu 15.04 'Vivid Vervet' offer a libassimp-dbg package.

You can try building Assimp from source with debugging information. See the Stack Overflow question Creating symbol table for gdb using cmake for instructions on how to do this.

Community
  • 1
  • 1
Daniel Trebbien
  • 38,421
  • 18
  • 121
  • 193
  • Thank you; so know I can go on with my project :) – Coder32 Jul 29 '15 at 12:21
  • @Coder32: Glad I could help. I still would recommend re-building Assimp with debugging information. In this particular case, the documentation indicates that your usage of Assimp is correct and that the library itself is leaking memory. In other cases, it might not be so clear. Having the debugging information will help you determine whether a leak within Assimp is a memory leak issue in the library, or if your application is using the library incorrectly, or if it's a false positive. – Daniel Trebbien Jul 29 '15 at 12:26
  • I don't think though this would be a true memory leak (based on this article here : http://stackoverflow.com/questions/2820285/abort-terminate-or-exit ) – Coder32 Jul 29 '15 at 14:41
  • The debug mode shall be supported by the Asset importer lib by default. – KimKulling Aug 04 '15 at 14:19