简体   繁体   中英

OpenGL Textures Causes Memory Issues

I'm having some weird memory issues in a C program I'm writing, and I think something related to my texture loading system is the cause.

The problem is that, depending on how many textures I make, different issues start coming up. Less textures tend to ever so slightly change other variables in the program. If I include all the textures I want to include, the program may spit out a host of different " * glibc detected * " type errors, and occasionally a Segmentation Fault. The kicker is that occasionally, the program works perfectly. It's all the luck of the draw.

My code is pretty heavy at this point, so I'll just post what I believe to be the relevant parts of it.

d_newTexture(d_loadBMP("resources/sprites/default.bmp"), &textures);

Is the function I call to load a texture into OpenGL. "textures" is a variable of type texMan_t, which is a struct I made.

typedef struct {
    GLuint texID[500];
    int texInc;
} texMan_t;

The idea is that texMan_t encompasses all your texture IDs for easier use. texInc just keeps track of what the next available member of texID is.

This is d_newTexture:

void d_newTexture(imgInfo_t info, texMan_t* tex) {

    glEnable(GL_TEXTURE_2D);

    glGenTextures(1, &tex->texID[tex->texInc]);
    glBindTexture(GL_TEXTURE_2D, tex->texID[tex->texInc]);
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

    gluBuild2DMipmaps( GL_TEXTURE_2D, 4, info.width, info.height, GL_RGBA, GL_UNSIGNED_BYTE, info.data );

    tex->texInc++;
    glDisable(GL_TEXTURE_2D);
}

I also use a function by the name of d_newTextures, which is identical to d_newTexture, except for that it splits up a simple sprite sheet into multiple textures.

void d_newTextures(imgInfo_t info, int count, texMan_t* tex) {
    glEnable(GL_TEXTURE_2D);

    glGenTextures(count, &tex->texID[tex->texInc]);
    for(int i=0; i<count; i++) {
        glBindTexture(GL_TEXTURE_2D, tex->texID[tex->texInc+i]);
        glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );

        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

        gluBuild2DMipmaps(  GL_TEXTURE_2D, 4, info.width, info.height/count, 
            GL_RGBA, GL_UNSIGNED_BYTE, &info.data[info.width*(info.height/count)*4*i] );
    }

    tex->texInc+=count;
    glDisable(GL_TEXTURE_2D);
}

What could be the cause of the issues I'm seeing?

EDIT: Recently, I've also been getting the error " * glibc detected out/PokeEngine: free(): invalid pointer: 0x01010101 * *" after closing the program as well, assuming it's able to properly begin. The backtrace looks like this:

/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xceeee2]
/usr/lib/nvidia-173/libGLcore.so.1(+0x277c7c)[0x109ac7c]

EDIT 2: Here's the code for d_loadBMP as well. Hope it helps!

imgInfo_t d_loadBMP(char* filename) {
    imgInfo_t out;

    FILE * bmpFile;
    bmpFile = fopen(filename, "r");
    if(bmpFile == NULL) {
        printf("ERROR: Texture file not found!\n");
    }

    bmp_sign bmpSig;
    bmp_fHeader bmpFileHeader;
    bmp_iHeader bmpInfoHeader;

    fread(&bmpSig, sizeof(bmp_sign), 1, bmpFile);
    fread(&bmpFileHeader, sizeof(bmp_fHeader), 1, bmpFile);
    fread(&bmpInfoHeader, sizeof(bmp_iHeader), 1, bmpFile);

    out.width = bmpInfoHeader.width;
    out.height = bmpInfoHeader.height;
    out.size = bmpInfoHeader.imageSize;

    out.data = (char*)malloc(sizeof(char)*out.width*out.height*4);

    // Loaded backwards because that's how BMPs are stored
    for(int i=out.width*out.height*4; i>0; i-=4) {
        fread(&out.data[i+2], sizeof(char), 1, bmpFile);
        fread(&out.data[i+1], sizeof(char), 1, bmpFile);
        fread(&out.data[i], sizeof(char), 1, bmpFile);

        out.data[i+3] = 255;
    }


    return out;
}

The way you're loading BMP files is wrong. You're reading right into structs, which is very unreliable, because the memory layout your compiler chooses for a struct may vastly differ from the data layout in a file. Also your code contains zero error checks. If I had to make an educated guess I'd say this is where your problems are.

BTW. glEnable(GL_TEXTURE_…) enables a texture target as data source for rendering. It's completely unnecessary for just generating and uploading textures. You can omit the bracing glEnable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D) blocks in your loading code. Also I'd not use gluBuildMipmaps2D – it doesn't support arbitrary texture dimensions, and you're disabling mipmapping anyway – and just upload directly with glTexImage2D .

Also I don't get your need for a texture manager. Or at least not why your texture manager looks like this. A much better approach would be using a hash map file path → texture ID and a reference count.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM