2013-04-08 6 views
0

У меня возникают некоторые странные проблемы с памятью в программе на языке C, которую я пишу, и я думаю, что причиной является то, что связано с моей системой загрузки текстур.Текстуры OpenGL вызывают проблемы с памятью

Проблема в том, что в зависимости от того, сколько текстур я создаю, возникают разные проблемы. Меньше текстур, как правило, немного меняют другие переменные в программе. Если я включу все текстуры, которые хочу включить, программа может выплеснуть множество различных ошибок типа «* glibc detected *», а иногда и ошибки сегментации. Кикер в том, что иногда программа работает отлично. Это все удача вничью.

Мой код довольно тяжелый на данный момент, поэтому я просто опубликую то, что, как я считаю, является его соответствующими частями.

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

Является функцией, которую я вызываю для загрузки текстуры в OpenGL. «Текстуры» - это переменная типа texMan_t, которую я создал.

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

Идея состоит в том, что texMan_t включает все ваши идентификаторы текстур для удобства использования. texInc просто отслеживает, что следующий доступный член texID.

Это 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); 
} 

Я также использовать функцию по имени d_newTextures, который идентичен d_newTexture, за исключением того, что он распадается простой спрайты листа в нескольких текстур.

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); 
} 

Что может быть причиной проблем, которые я вижу?

EDIT: В последнее время я также получаю ошибку «* Glibc обнаружен из/PokeEngine: свободный(): недопустимый указатель: 0x01010101 * *» после закрытия программы, а также, при условии, что в состоянии правильно начать. Трассировку выглядит следующим образом:

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

EDIT 2: Вот код d_loadBMP, а также. Надеюсь, поможет!

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; 
} 
+0

Вы уверены, что 'texInc' никогда не превышает размер' texID'? Многое плохое может произойти, если вы начнете перезаписывать память за пределами своей структуры. Ваш OpenGL выглядит разумно, но я подозреваю, что для того, чтобы действительно найти проблему, требуется дополнительная информация. – radical7

+0

@ radical7 Эта возможность тоже перешла мне на ум, но я это испытал. Я продолжу и добавлю код для 'd_loadBMP', но я не могу думать о том, что еще включить. – Velovix

ответ

0

То, как вы загружаете файлы BMP, неверно. Вы читаете право на структуры, что очень ненадежно, потому что макет памяти, который ваш компилятор выбирает для структуры, может значительно отличаться от макета данных в файле. Также ваш код содержит нулевые проверки ошибок. Если бы я должен был дать обоснованное предположение, я бы сказал, что это ваши проблемы.

BTW. glEnable(GL_TEXTURE_…) позволяет использовать объект текстуры как источник данных для рендеринга. Для создания и загрузки текстур совершенно необязательно. Вы можете опустить блокировку glEnable(GL_TEXTURE_2D); ... glDisable(GL_TEXTURE_2D) блоков в вашем коде загрузки. Также я бы не использовал gluBuildMipmaps2D - он не поддерживает произвольные размеры текстур, и вы все равно отключите mipmapping - и просто загружайте напрямую с помощью glTexImage2D.

Также у меня нет необходимости в менеджере текстур. Или, по крайней мере, не потому, что ваш менеджер текстур выглядит так.Гораздо лучший подход был бы использовать хэш-таблицу путь к файлу → текстура ID и счетчик ссылок.

+0

Оказывается, текстурирование на самом деле не было источником проблемы, это было в другой части программы. Тем не менее, ты дал мне хороший совет, так что спасибо! – Velovix