In the course of my application I create a 2048x2048 texture which then gets updated periodically. Every few times this texture gets updated via a glTexSubImage2D call there is a significant hit on the available memory of the system which never appears to be released.

I've attached a full application that demonstrates how I'm using this texture in my real application and having tested it find that this has the same memory issue as my real application. Can anyone see something I'm not doing properly that might account for this memory growth?

Code :
#define GL_GLEXT_PROTOTYPES
 
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <iostream>
#include <fstream>
using namespace std;
 
GLuint texid(0);
unsigned char rawTex[2048*2048*3];
int totalMem(0), freeMem(0);
 
void GetMemUsage (void)
{
  unsigned char rawData[512];
 
  memset(rawData, 0, sizeof(rawData));
  fstream f;
  f.open("/proc/meminfo", ios::in|ios::binary);
 
  if (f.is_open()) {
    f.read((char*) rawData, 512);
    f.close();
 
    char *ptr(0);
 
    ptr = strstr((char*)rawData, (const char*)"MemTotal:");
    if (ptr != 0) {
      totalMem = atoi(ptr+strlen("MemTotal:"));
    }
    ptr = 0;
    ptr = strstr((char*) rawData, (const char*)"MemFree:");
    if (ptr != 0) {
      freeMem = atoi(ptr+strlen("MemFree:"));
    }    
  }
}
 
void SetBitmap(void)
{
  static int init(0);
 
  if (!init) {
    memset(rawTex, 0xA0, sizeof(rawTex));
  } else {
    memset(rawTex, 0xFF, sizeof(rawTex));
  }
  init ^= 1;
}
 
void Display (void)
{
  char txtString[120];
 
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glEnable(GL_TEXTURE_2D);
 
  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, texid);
  glBegin(GL_TRIANGLES);
 
  glTexCoord2f(0.0, 0.0); 
  glVertex2f(-1, 0);
  glTexCoord2f(0.0, 1.0); 
  glVertex2f(-1, 1);
  glTexCoord2f(1.0, 0.0); 
  glVertex2f(0, 0);
 
  glTexCoord2f(0.0, 1.0); 
  glVertex2f(-1, 1);
  glTexCoord2f(1.0, 0.0); 
  glVertex2f(0, 0);
  glTexCoord2f(1.0, 1.0); 
  glVertex2f(0, 1);
 
  glEnd();
  glDisable(GL_TEXTURE_2D);
 
  GetMemUsage();
  snprintf(txtString, 120, "Total(%d) Free(%d) Per(%f)", totalMem, freeMem, freeMem / ((float) totalMem));
  glRasterPos2i(0, 0);
  glColor4f(1.0f, 0.0f, 1.0f, 1.0f);
  glutBitmapString(GLUT_BITMAP_HELVETICA_18, (const unsigned char*) txtString);
 
  glutSwapBuffers();
  glutPostRedisplay();
  return;
}
 
void Keyboard(unsigned char key, int x, int y)
{
  switch(key) {
  case 'n':
    SetBitmap();
    glBindTexture(GL_TEXTURE_2D, texid);    // Bind the texture
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2048, 2048, GL_RGB, GL_UNSIGNED_BYTE, rawTex);
    break;
  default:
    break;
  }
  return;
}
 
void InitTexture (void)
{
    // Initially Load the texture
    glGenTextures(1, &texid);               // Creates the texture
    glBindTexture(GL_TEXTURE_2D, texid);    // Bind the texture
    /*
     *  Set edge handling
     */
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    /*
     * Set filtering
     */
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
    /*
     * Upload the texture to GL
     */
    glTexImage2D(GL_TEXTURE_2D,             // 2D Texture
                 0,                         // level
                 GL_RGB,                    // internal formal
                 2048,                      // width
                 2048,                      // height
                 0,                         // border
                 GL_RGB,                    // format
                 GL_UNSIGNED_BYTE,          // type
                 rawTex);                   // data
}
 
int main (int argc, char *argv[])
{
  GLint mainWindow;
 
  glutInit (&argc, argv);
  SetBitmap();
 
  glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
 
  glutInitWindowSize (1024, 768);
  mainWindow = glutCreateWindow("Texture Test");
 
  glutDisplayFunc(Display);
  glutKeyboardFunc(Keyboard);
 
  glShadeModel(GL_SMOOTH);
  glEnable(GL_BLEND);
  glEnable(GL_NORMALIZE);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glCullFace(GL_FRONT);
  InitTexture();
 
  glutPostRedisplay();
  glutMainLoop();
 
  cout << "Freeing Memory!" << endl;
  glDeleteTextures(1, &texid);
 
  return 0;    
}