Thread: Stack corruption driving me insane
hi guys,
i've been stuck on problem ages , can't seem figure out, i'm hoping whoever reads can. i'm writing small game engine hobby in spare time, it's not working planned.
problem whenever member function 'loadtexture(char *cname)' called msvc debugger says "run-time check failure #2 - stack around variable 'image' corrupted." have no problem googling programming problems, i've been stuck on 1 hours without straight answer.
here header file class:
and here source file:code:// graphicsdevice.h #ifndef h_graphics_device #define h_graphics_device #include "graphicsinstance.h" #include <sfml/window.hpp> #include <sfml/graphics.hpp> #include <gl/gl.h> #include <gl/glu.h> #include <vector> using std::vector; #define max_windows 10 #define max_entities 10000 #define array_resize_amount 50 //defines how arrays resize (50 means arrays expand 50 spaces @ time) #define max_depth 100000//the maximum positive or negative number graphics instance's depth can using namespace std; //this can inhereted purposes of expanding engine rendering api class graphicsdevice { public: graphicsdevice(void); ~graphicsdevice(void); int createrenderingwindow(int winwidth, int winheight, int colourdepth, char *title, bool fullscreen, int antialiasing); int destroyrenderingwindow(); int updategraphics(); int updatewindow(); nanotexture *loadtexture(char *cname);//loads texture , returns pointer it, or pointer if loaded int instanceattach(graphicsinstance *instance); int instancedetach(graphicsinstance *instance); void setbackgroundcolour(float red, float green, float blue); float getframetime(void); void resortdepth(void); sf::renderwindow *getsfmlwindow(); private: //private member functions: void reshape(int x, int y); //reshapes opengl viewport given new width , height of window void rotatepoint(float cx, float cy, float angle, float *px, float *py); //rotates (px, py) around (cx, cy) //resorts graphicsinstances front based on depth, n number of graphicsinstances void sortentities (int n); //rendering settings: sf::renderwindow *wwindow; bool bwinfocused; int iwinwidth; int iwinheight; bool bwinclosed; int icolourdepth; int iantialiasing; //instance information: unsigned int iinstancecount; vector<graphicsinstance *> entities; unsigned int iinstancearraysize; //resources: unsigned int itexturecount; unsigned int itexturearraysize; vector<auto_ptr<nanotexture> > ptextures; vector<gluint> vtexture; //bg colour: float fbgred; float fbggreen; float fbgblue; //depth sorting: bool bdepthsortneeded; //only testing purposes: int x; float fps; }; #endif
could give possible cause what's causing error? can tell i'm new c++, other programming tips appreciated.code:#include "stdafx.h" #include "graphicsdevice.h" graphicsdevice::graphicsdevice(void) { //instances iinstancecount = 0; iinstancearraysize = 0; wwindow = null; //rendering settings: bwinfocused = false; iwinwidth = 0; iwinheight = 0; bwinclosed = true; icolourdepth = 0; iantialiasing = 0; //resources: itexturecount = 0; itexturearraysize = 0; //bg colour: float fbgred = 0; float fbggreen = 0; float fbgblue = 0; //depth sorting: bdepthsortneeded = false; //only testing purposes: x = 0; fps = 0; } graphicsdevice::~graphicsdevice(void) { //release textures for (uint i=0; i<itexturecount; i++) { std::cout << "deleting texture id " << << " out of " << itexturecount-1 << endl; //gldeletetextures(1, (gluint*)ptextures[i].get()->textureid); gldeletetextures(1, (gluint*)vtexture[i]); } if (bwinclosed == false) { wwindow->close(); delete wwindow; } } int graphicsdevice::createrenderingwindow(int winwidth, int winheight, int colourdepth, char *title, bool fullscreen, int antialiasing) { #ifdef _debug cout << "creating rendering window following properties:\n" << "\twidth: " << winwidth << "\n\theight: " << winheight << "\n\tcolour depth: " << colourdepth << "\n\tfullscreen: " << fullscreen << "\n\tanti-aliasing: " << antialiasing <<"\n"; #endif if (bwinclosed == false) { #ifdef _debug cout << "error: cannot create new rendering window because 1 exists\n"; #endif } //record arguments iantialiasing = antialiasing; icolourdepth = colourdepth; iwinwidth = winwidth; iwinheight = winheight; //set settings sf::windowsettings settings; settings.depthbits = 24; // request 24 bits depth buffer settings.stencilbits = 8; // request 8 bits stencil buffer settings.antialiasinglevel = iantialiasing; // request 2 levels of antialiasing //create new window if (fullscreen == true) { wwindow = new sf::renderwindow(sf::videomode(iwinwidth, iwinheight, icolourdepth), title, sf::style::fullscreen, settings); } else { wwindow = new sf::renderwindow(sf::videomode(iwinwidth, iwinheight, icolourdepth), title, /*sf::style::fullscreen, sf::style::close*/sf::style::resize, settings); } //windows start focused: bwinfocused = true; bwinclosed = false; #ifdef _debug cout << "window created successfully\n"; #endif return 0; } int graphicsdevice::destroyrenderingwindow() { //destroy window if (bwinclosed == false) { wwindow->close(); bwinclosed = true; #ifdef _debug cout << "rendering window destroyed.\n"; #endif } else { #ifdef _debug cout << "error: cannot destroy rendering window because doesn't exist.\n"; #endif return -1; } return 0; } int graphicsdevice::updategraphics() { //check if window has been closed if (bwinclosed == true) { #ifdef _debug cout << "error: cannot swap buffers closed window.\n"; #endif return -1; } //check see if graphicsinstances need put in order if (bdepthsortneeded == true) { sortentities(iinstancecount); bdepthsortneeded = false; } //must called before rendering window (only needed when doing multiple windows meh) wwindow->setactive(); //resize opengl viewport window rendering. todo: put on resize event reshape(iwinwidth, iwinheight); //enable depth testing glcleardepth(1.0f); // depth buffer setup glenable(gl_depth_test); // enables depth testing gldepthfunc(gl_lequal); //set clear colour glclearcolor(fbgred, fbggreen, fbgblue, 1); //clear screen glclear(gl_color_buffer_bit | gl_depth_buffer_bit); int vport[4]; glgetintegerv(gl_viewport, vport); glmatrixmode(gl_projection); glpushmatrix(); glloadidentity(); glortho(0, vport[2], 0, vport[3], max_depth*-1, max_depth);//last 2 arguments near (close screen) , far (view distance) clipping glmatrixmode(gl_modelview); glpushmatrix(); //prevents pixel blur occuring since pixel coordinates not aligned window glloadidentity(); gltranslatef (0.375, 0.375, 0);//0.5 formerly 0.375 //enable transparency rendering in gl primatives (if glenable (gl_blend);) glblendfunc (gl_src_alpha, gl_one_minus_src_alpha); //make depth buffer read while render(for transparency effects) //now don"t need because being drawn in order gldepthmask(gl_false); //variables need rendering: nanotexture *ntrendertexture = null; //this used handle each graphicsinstance's texture float frenderangle = 0.0f; //this used handle each graphicsinstance's rotation float fdepth = 0; //this used handle each graphicsinstance's depth float frenderpointtlx, frenderpointtrx, frenderpointblx, frenderpointbrx; //the x points opengl render float frenderpointtly, frenderpointtry, frenderpointbly, frenderpointbry; //the y points opengl render //render entities: for (unsigned int = iinstancecount-1; i>=0; i--)//for attached instances graphicsinstance (in reverse render properly) { if (entities[i]) //if 1 exists { if (entities[i]->getvisible() == true) //if graphicsinstance set visible { ntrendertexture = entities[i]->gettexture(); if (ntrendertexture != null) //if graphicsinstance has image render { //collect needed details given instance: frenderangle = entities[i]->getrotation(); fdepth = (float)(entities[i]->getdepth()*-1);//we multiply -1 higher depth goes deeper screen //cout << "drawing instance @ depth " << entities[i]->getdepth() << endl; //set initial position of 4 points: frenderpointtlx = entities[i]->getpositionx() - entities[i]->getoriginx(); frenderpointtly = entities[i]->getpositiony() - entities[i]->getoriginy(); frenderpointtrx = frenderpointtlx + entities[i]->getscalex(); frenderpointtry = frenderpointtly; frenderpointblx = frenderpointtlx; frenderpointbly = frenderpointtly + entities[i]->getscaley(); frenderpointbrx = frenderpointtrx; frenderpointbry = frenderpointbly; //rotate 4 points: if (frenderangle != 0)//if rotation has been modified { rotatepoint(entities[i]->getpositionx(), entities[i]->getpositiony(), frenderangle, &frenderpointtlx, &frenderpointtly); rotatepoint(entities[i]->getpositionx(), entities[i]->getpositiony(), frenderangle, &frenderpointtrx, &frenderpointtry); rotatepoint(entities[i]->getpositionx(), entities[i]->getpositiony(), frenderangle, &frenderpointbrx, &frenderpointbry); rotatepoint(entities[i]->getpositionx(), entities[i]->getpositiony(), frenderangle, &frenderpointblx, &frenderpointbly); } // bind our texture glenable(gl_texture_2d); glbindtexture(gl_texture_2d, (gluint)ntrendertexture->textureid); glcolor4f(1.f, 1.f, 1.f, 1.f); //modify rendering settings if (entities[i]->getqualitytransparent() == false) { glalphafunc(gl_greater, (glclampf)0.9);//set alpha test ignore pixels below 90% alpha, , make top 10% opaque glenable(gl_alpha_test);//enable alpha test } else { glenable(gl_blend);//enable alpha blending } //check if depth appropriate (debug only) #ifdef _debug if (fdepth < (max_depth*-1) || fdepth > max_depth) { cout << "warning: attempting render object depth less -" << max_depth << " or greater " << max_depth << ". texture may not appear\n"; } #endif /*render graphicsinstance using collected details (all points on y axis multiplied -1 invert y axis higher y moves points downwards. not second argument of gltexcoord2f must be inverted)*/ glbegin(gl_quads); //bottom-left gltexcoord2f(0, 1); glvertex3f(frenderpointblx, (frenderpointbly * -1) + iwinheight, fdepth); //bottom-right gltexcoord2f(1, 1); glvertex3f(frenderpointbrx, (frenderpointbry * -1) + iwinheight, fdepth); //top-right gltexcoord2f(1, 0); glvertex3f(frenderpointtrx, (frenderpointtry * -1) + iwinheight, fdepth); //top-left gltexcoord2f(0, 0); glvertex3f(frenderpointtlx, (frenderpointtly * -1) + iwinheight, fdepth); glend(); //unmodify rendering settings if (entities[i]->getqualitytransparent() == false) { gldisable(gl_alpha_test);//enable alpha test } else { gldisable(gl_blend);//enable alpha blending } } } } else { #ifdef _debug cout << "bug: null instance attached\n"; #endif } //check if on last loop(fixes bug loop running in reverse) if (i==0) break; } //make depth buffer writable again (for transparency effects) //now don"t need because being drawn in order gldepthmask(gl_true); #ifdef _debug //display frame time x++; fps += getframetime(); if (fps > 5) { cout << "fps: " << x/(float)5 << endl; x = 0; fps = 0; } /* if (x > 20000) { cout << "average fps:" << fps/(float)x << endl; x = 0; fps = 0; }*/ #endif //update window wwindow->display(); return 0; } int graphicsdevice::updatewindow() { sf::event event; while (wwindow->getevent(event)) { // window closed if (event.type == sf::event::closed) { wwindow->close(); bwinclosed = true; } // window resize if (event.type == sf::event::resized) { iwinwidth = event.size.width; iwinheight = event.size.height; } // window focused if (event.type == sf::event::gainedfocus) { bwinfocused = true; } // window focused if (event.type == sf::event::lostfocus) { bwinfocused = false; } } return 0; } nanotexture *graphicsdevice::loadtexture(char *cname) { unsigned int itex, n = 0; // have texture? if so, ignore for (itex=0; itex<itexturecount; itex++) { if (ptextures[itex].get()->sname.c_str()==cname) { return ptextures[itex].get();//error non fatal } } // allocate array_resize_amount new memory slots textures if necessary if (itexturecount == itexturearraysize) { itexturearraysize += array_resize_amount; ptextures.resize(itexturearraysize); vtexture.resize(itexturearraysize); #ifdef _debug cout << "expanding texture memory " << itexturearraysize << " textures\n"; #endif } //create new nanotexture ptextures[itexturecount].reset(new nanotexture); //save texture name ptextures[itexturecount].get()->sname = cname; //create new sf::image sf::image image; //loads texture in sfml #ifdef _debug cout << "loading '" << ptextures[itexturecount].get()->sname << "' id " << itexturecount << "\n"; #endif if (image.loadfromfile(ptextures[itexturecount].get()->sname)) { #ifdef _debug cout << "error: failed loading texture '" << ptextures[itexturecount].get()->sname << "'\n"; #endif return null; } //record textures dimensions ptextures[itexturecount].get()->fwidth = (float)image.getwidth(); ptextures[itexturecount].get()->fheight = (float)image.getheight(); //record opengl info texture glgentextures(1, &vtexture[itexturecount]); glbindtexture(gl_texture_2d, vtexture[itexturecount]); gltexparameteri(gl_texture_2d, gl_texture_mag_filter, gl_linear); gltexparameteri(gl_texture_2d, gl_texture_min_filter, gl_linear_mipmap_linear); glubuild2dmipmaps(gl_texture_2d, gl_rgba, image.getwidth(), image.getheight(), gl_rgba, gl_unsigned_byte, image.getpixelsptr()); //records texture id ptextures[itexturecount].get()->textureid = (unsigned int)vtexture[itexturecount]; //we have texture loaded itexturecount++; //everything return ptextures[itexturecount-1].get(); } int graphicsdevice::instanceattach(graphicsinstance *instance) { //check if given instance real if (!instance) { #ifdef _debug cout << "error: cannot attach non-valid graphicsinstance\n"; #endif return -1; } //check if instance exists for (unsigned int = 0; i<iinstancearraysize; i++) { if (entities[i]==instance) { return 0; } } //check if have room more entities. if not, make room. while (iinstancecount>=iinstancearraysize) { iinstancearraysize += array_resize_amount; entities.resize(iinstancearraysize); } //point instance entities[iinstancecount] = instance; //make sure knows it's attached if (entities[iinstancecount]->getattached() == false)//if doesn't know entities[iinstancecount]->attach(this); iinstancecount++; return 0; } int graphicsdevice::instancedetach(graphicsinstance *instance) { //check if instance exists for (unsigned int = 0; i<iinstancearraysize; i++) { if (entities[i]==instance) { //make sure instance knows it's being detached if (entities[i]->getattached() == true)//if doesn't know //i formerly iinstancecount entities[i]->attach(this); //shift entities above requested 1 down list 1 slot for (unsigned int ii = i; ii<iinstancearraysize-1; ii++) //run loop till second last instance { entities[ii] = entities[ii+1];//make 1 equal 1 in front of } entities[iinstancearraysize-1] = null; //decrement total number of entities iinstancecount -= 1; //shrink array if needed if ((iinstancearraysize-i)>array_resize_amount) { iinstancearraysize -= array_resize_amount; entities.resize(iinstancearraysize); } return 0; } } //if nothing found #ifdef _debug cout << "error: can't detach graphicsinstance doesn't exist\n"; #endif return -1; } void graphicsdevice::setbackgroundcolour(float red, float green, float blue) { fbgred = red; fbggreen = green; fbgblue = blue; } float graphicsdevice::getframetime(void) { return wwindow->getframetime(); } void graphicsdevice::reshape(int x, int y) { if (y == 0 || x == 0) return; //nothing visible then, return glviewport(0, 0, x, y); } void graphicsdevice::rotatepoint(float cx, float cy, float angle, float *p_x, float *p_y) { float s = sin(angle); float c = cos(angle); // translate point origin: *p_x -= cx; *p_y -= cy; // rotate point float xnew = (*p_x) * c - (*p_y) * s; float ynew = (*p_x) * s + (*p_y) * c; // translate point back: *p_x = xnew + cx; *p_y = ynew + cy; } void graphicsdevice::resortdepth(void) { //this means sort depths before frame rendered, preventing multiple changes //in depth during 1 frame wasting cpu cycles bdepthsortneeded = true; } void graphicsdevice::sortentities (int n) { graphicsinstance *t; // temporary value unsigned int n = n, parent = n/2, index, child; // heap indexes // loop until array sorted (;;) { if (parent > 0) { // first stage - sorting heap t = entities[--parent]; // save old value t } else { // second stage - extracting elements in-place n--; // make heap smaller if (n == 0) return; // when heap empty, done t = entities[n]; // save lost heap entry temporary entities[n] = entities[0]; // save root entry beyond heap } // insert operation - pushing t down heap replace parent index = parent; // start @ parent index child = index * 2 + 1; // left child index while (child < n) { // choose largest child if (child + 1 < n && entities[child + 1]->getdepth() > entities[child]->getdepth()) { child++; // right child exists , bigger } // largest child larger entry? if (entities[child]->getdepth() > t->getdepth()) { entities[index] = entities[child]; // overwrite entry child index = child; // move index child child = index * 2 + 1; // left child , go around again } else { break; // t's place found } } // store temporary value @ new location entities[index] = t; } } sf::renderwindow *graphicsdevice::getsfmlwindow() { return wwindow; }
edit: when don't declare 'sf::image image;' local variable 'loadtexture(char *cname)' , instead declare private member of class, upon class being destroyed says displays error notifying me of heap corruption, instead of usual stack corruption notification. hope helps.
can give sample call loadtexture?
1 thing sets off alarm bells usage of char* if strings; e.g.
checks pointer returned ptextures[itex].get()->sname.c_str() equal pointer cname (not strings equal!) - pretty unlikely case in practicecode:ptextures[itex].get()->sname.c_str()==cname
and
this stores pointer cname sname, might not want - if cname e.g. passed in local stack object function , function went out of scope, sname dangling pointer. (there plenty of other situations cause similar problem).code:ptextures[itexturecount].get()->sname = cname;
edit:
general points: when writing c++ apps, std::string preferred raw char*'s. also, many people prefer scope of variables minimal possible, means (at least) declared close point @ first used possible. e.g. in loadtexture, we'd have
instead of declaring itex @ top of block (assuming there no other references itex outside ... loop - didn't see @ quick glancecode:for (unsigned int itex=0; itex<itexturecount; itex++))
also, purely subjective , stylistic choice - many people thoroughly loathe hungarian notation![]()
Forum The Ubuntu Forum Community Ubuntu Specialised Support Development & Programming Programming Talk Stack corruption driving me insane
Ubuntu
Comments
Post a Comment