Porting from VC6 to Linux Fedora core 5 problem
Hi, I'm a new member in the forum. I have quite a problem here. Actually, I've posted it in www.cprogramming.com, but since I needed it to be resolved fast, I post it here also.
Recently, I ported my codes from Visual C 6 to Linux. But, what I meant about porting was only copy-pasted the entire code to a new KDevelop C/C++ project (also a little letter-case correction in the #include line ). The code was successfully compiled and built. But when I run it, there's a memory corruption error. I don' tknow what's wrong with it because it never happened before in VC6. The error was in the "myVector.push_back(mObject) ". And the myVector declaration was "vector<*MyObject> myVector". The strange thing was not all of the push_back methods was faulty. Only a few of them. And it gets more strange because when I moved the faulty method to the beginning of the function, it worked fine until the next push_back method. Here's the error message:
*** glibc detected *** ./mattinggame: malloc(): memory corruption:
0x09f67f70 ***
*
======= Backtrace: =========
/lib/libc.so.6[0xb49660]
/lib/libc.so.6(malloc+0x74)[0xb4ac7c]
/usr/lib/libstdc++.so.6(_Znwj+0x27)[0x220e4d7]
/usr/lib/libstdc++.so.6(_Znaj+0x1d)[0x220e60d]
./mattinggame[0x8056536]
./mattinggame[0x80567bb]
./mattinggame[0x80578c5]
./mattinggame[0x8057cb2]
./mattinggame[0x8057dd8]
./mattinggame[0x8052b49]
./mattinggame[0x807364c]
./mattinggame[0x807a5ff]
./mattinggame(__gxx_personality_v0+0x1de)[0x80499c2]
/lib/libc.so.6(__libc_start_main+0xdc)[0xafa7e4]
./mattinggame(__gxx_personality_v0+0x9d)[0x8049881]
======= Memory map: ========
001bb000-001be000 r-xp 00000000 fd:00 92170 /usr/lib/libXrandr.so.2.0.0
001be000-001bf000 rwxp 00002000 fd:00 92170 /usr/lib/libXrandr.so.2.0.0
001dd000-001e8000 r-xp 00000000 fd:00 3457623
/lib/libgcc_s-4.1.0-20060304.so.1
001e8000-001e9000 rwxp 0000a000 fd:00 3457623
/lib/libgcc_s-4.1.0-20060304.so.1
00215000-00216000 r-xp 00215000 00:00 0 [vdso]
00258000-00271000 r-xp 00000000 fd:00 3457612 /lib/ld-2.4.so
00271000-00272000 r-xp 00018000 fd:00 3457612 /lib/ld-2.4.so
00272000-00273000 rwxp 00019000 fd:00 3457612 /lib/ld-2.4.so
00548000-00592000 r-xp 00000000 fd:00 75310
/usr/local/lib/libSDL_mixer-1.2.so.0.2.5
00592000-0059c000 rwxp 0004a000 fd:00 75310
/usr/local/lib/libSDL_mixer-1.2.so.0.2.5
0059c000-005c0000 rwxp 0059c000 00:00 0
00680000-006e3000 r-xp 00000000 fd:00 71301
/usr/local/lib/libSDL-1.2.so.0.11.0
006e3000-006e5000 rwxp 00063000 fd:00 71301
/usr/local/lib/libSDL-1.2.so.0.11.0
006e5000-00700000 rwxp 006e5000 00:00 0
00ae5000-00c11000 r-xp 00000000 fd:00 3457618 /lib/libc-2.4.so
00c11000-00c14000 r-xp 0012b000 fd:00 3457618 /lib/libc-2.4.so
00c14000-00c15000 rwxp 0012e000 fd:00 3457618 /lib/libc-2.4.so
00c15000-00c18000 rwxp 00c15000 00:00 0
00c1a000-00c3d000 r-xp 00000000 fd:00 3457619 /lib/libm-2.4.so
00c3d000-00c3e000 r-xp 00022000 fd:00 3457619 /lib/libm-2.4.so
00c3e000-00c3f000 rwxp 00023000 fd:00 3457619 /lib/libm-2.4.so
00c41000-00c43000 r-xp 00000000 fd:00 3457620 /lib/libdl-2.4.so
00c43000-00c44000 r-xp 00001000 fd:00 3457620 /lib/libdl-2.4.so
00c44000-00c45000 rwxp 00002000 fd:00 3457620 /lib/libdl-2.4.so
00c47000-00d40000 r-xp 00000000 fd:00 92167 /usr/lib/libX11.so.6.2.0
00d40000-00d44000 rwxp 000f9000 fd:00 92167 /usr/lib/libX11.so.6.2.0
00d46000-00d48000 r-xp 00000000 fd:00 92165 /usr/lib/libXau.so.6.0.0
00d48000-00d49000 rwxp 00001000 fd:00 92165 /usr/lib/libXau.so.6.0.0
00d60000-00d65000 r-xp 00000000 fd:00 92166 /usr/lib/libXdmcp.so.6.0.0
00d65000-00d66000 rwxp 00004000 fd:00 92166 /usr/lib/libXdmcp.so.6.0.0
00d68000-00d77000 r-xp 00000000 fd:00 92169 /usr/lib/libXext.so.6.4.0
00d77000-00d78000 rwxp 0000e000 fd:00 92169 /usr/lib/libXext.so.6.4.0
00dc7000-00dcf000 r-xp 00000000 fd:00 92168 /usr/lib/libXrender.so.1.3.0
00dcf000-00dd0000 rwxp 00007000 fd:00 92168 /usr/lib/libXrender.so.1.3.0
00dd2000-00de2000 r-xp 00000000 fd:00 3457622 /lib/libpthread-2.4.so
00de2000-00de3000 r-xp 0000f000 fd:00 3457622 /lib/libpthread-2.4.so
00de3000-00de4000 rwxp 00010000 fd:00 3457622 /lib/libpthread-2.4.so
00de4000-00de6000 rwxp 00de4000 00:00 0
00de8000-00df1000 r-xp 00000000 fd:00 92172 /usr/lib/libXcursor.so.1.0.2
00df1000-00df2000 rwxp 00008000 fd:00 92172 /usr/lib/libXcursor.so.1.0.2
00df4000-00df8000 r-xp 00000000 fd:00 92171 /usr/lib/libXfixes.so.3.0.0
00df8000-00df9000 rwxp 00003000 fd:00 92171 /usr/lib/libXfixes.so.3.0.0
02157000-02239000 r-xp 00000000 fd:00 92179 /usr/lib/libstdc++.so.6.0.8
02239000-0223d000 r-xp 000e2000 fd:00 92179 /usr/lib/libstdc++.so.6.0.8
0223d000-0223e000 rwxp 000e6000 fd:00 92179 /usr/lib/libstdc++.so.6.0.8
0223e000-02244000 rwxp 0223e000 00:00 0
08048000-08087000 r-xp 00000000 fd:00 1533373
/home/benang/mattinggame/debug/src/mattinggame
08087000-08088000 rw-p 0003e000 fd:00 1533373
/home/benang/mattinggame/debug/src/mattinggame
098e0000-09d85000 rw-p 098e0000 00:00 0 [heap]
b4a00000-b4a21000 rw-p b4a00000 00:00 0
b4a21000-b4b00000 ---p b4a21000 00:00 0
b4b2d000-b6a5d000 rw-p b4b2d000 00:00 0
b6a5d000-b6b89000 rw-s 00000000 00:08 3112963 /SYSV00000000 (deleted)
b6b89000-b6b8a000 ---p b6b89000 00:00 0
b6b8a000-b758a000 rw-p b6b8a000 00:00 0
b758a000-b758b000 ---p b758a000 00:00 0
b758b000-b7f8e000 rw-p b758b000 00:00 0
b7fa6000-b7fa9000 rw-p b7fa6000 00:00 0
bff93000-bffa9000 rw-p bff93000 00:00 0 [stack]
/bin/sh: line 1: 27410 Aborted ./mattinggame
BTW, I've changed the code into MyObject **mObject and the object was created by :"mObject = new MyObject[mCount]". It worked fine until a while. When I uncommented a large part of the code, it gone berserk again.
Can anybody help me here?? I'm desperate to a suicidal point here (well, maybe suicidal is a bit too much, but it sure give me a nightmare). Thanks in advance.
Re: Porting from VC6 to Linux Fedora core 5 problem
Seems like a heap corruption issue.. By the way - can you post the minimal code that replicates the issue on your machine?
Re: Porting from VC6 to Linux Fedora core 5 problem
Well, I can't give you the full code cause it has already evolving into a "small" giant. Here's a part of it though:
in main
Code:
int main(argc,argv)
{
CImageHandler* mImgHandler; //Object for handling pointer to bitmap images
mImgHandler = new mImgHandler("ImgHandler.cfg"); //Constructor with a filename consisting the names of Bitmap Images
//Objects that will be displayed in the surface
CObjectScene* mObject1;
CObjectScene* mObject2;
CObjectScene* mObject3;
CObjectScene* mObject4;
.... //There's a lot of objects
mObject1 = new CObjectScene(mImgHandler, "Obj1.cfg");
mObject2 = new CObjectScene(mImgHandler, "Obj2.cfg");
mObject3 = new CObjectScene(mImgHandler, "Obj3.cfg");
mObject4 = new CObjectScene(mImgHandler, "Obj4.cfg"); //ERROR here!!!
...... //Other objects constructions
/*
Some rendering loop functions
*/
return 0;
}
in CImageHandler
Code:
typedef map<string, CBmpImage *> lstImage;
typedef lstImage::iterator itrImage;
class CImageHandler
{
public:
//Constructor
CImageHandler(char* filename)
{
char imgname[255], filename[255];
CBmpImage* tempImg;
char buffer[255];
FILE *fp=fopen(filename,"r");
/* Function to extract the configuration of each images from the file. Consist of image's name & image filename*/
while(!feof(fp))
{
fgets(buffer,255,fp);
sscanf(buffer,"%s %s",imgname, filename);
tempImg = new CBmpImage(imgname, filename); //Create & insert image to map
mImages[imgname]=tempImg;
}
fclose(fp);
}
CBmpImage* getImage(string name)
{
return mImages.find(name)->second;
}
private:
lstImage mImages;
}
in the CObjectScene
Code:
struct AnimFrame
{
CBmpImage *theImg;
int delay;
};
typedef vector<AnimFrame *> lstFrames; //List of an animation's frames
typedef lstImage::iterator itrFrames;
class CObjectScene
{
public:
CObjectScene(CImageHandler *imghandler, char* filename)
{
char imgname[255];
int tempdelay;
char buffer[255];
FILE *fp=fopen(filename,"r");
/* Function to extract the configuration of each objects from the file. Consist of image's name & delay to the next frame*/
while(!feof(fp))
{
fgets(buffer,255,fp);
sscanf(buffer,"%s %d",imgname, tempdelay);
AnimFrame *temp = new AnimFrame;
temp->theImg=imghandler->getImage(imgname);
temp->delay=tempdelay;
mFrames.push_back(temp); //ERROR here for the 4th object. The other previous objects are fine.
}
fclose(fp);
}
private:
lstFrames mFrames;
}
Can you help me please?
Re: Porting from VC6 to Linux Fedora core 5 problem
I have suspected the cause but I didn't quite sure. In making the CBmpImage objects in CImageHandler, I used this code:
Code:
.....
CBmpImage
{
public:
CBmpImage(char* imgname,char* filename)
{
mName= new char[strlen(imgname)];
strcpy(mName,imgname);
loadBmp(filename);
}
private:
char* mName;
}
.....
I suspected the :
Code:
mName= new char[strlen(imgname)];
strcpy(mName,imgname);
code because I can't delete the mName in the class's destructor. Anybody can give me some enlightment here? Please???
Re: Porting from VC6 to Linux Fedora core 5 problem
This is wrong:
Code:
mObject1 = new CObjectScene(mImgHandler, "Obj1.cfg");
mObject1 = new CObjectScene(mImgHandler, "Obj2.cfg");
mObject1 = new CObjectScene(mImgHandler, "Obj3.cfg");
mObject1 = new CObjectScene(mImgHandler, "Obj4.cfg"); //ERROR here!!!
there are leaks - all memory allocations are lost track of because you are using only one pointer to hold them.. correct it. Why are you not using arrays... Or make a collection class of CObjectScene that takes a vector of filenames and creates those many objects and stores them in a internal container. That would encapsulate all the nasty things that you do in main...
Also, use std::string class for holding strings instead of those C-style character arrays... they will remove cases where manually injecting code can cause errors.
Re: Porting from VC6 to Linux Fedora core 5 problem
Here is another problem:
Code:
CImageHandler(char* filename)
{
char imgname[255], filename[255];
You have a parameter called "filename", then you have an array called "filename".
Also, as exterminator pointed out, you can simplify the code greatly if you just stuck with std::string and not introduce char pointers:
Code:
#include <string>
class CBmpImage
{
public:
CBmpImage(const std::string& imgname, const std::string& filename) :
mName( imgname )
{
loadBmp(filename.c_str());
}
private:
std::string mName;
};
You have another problem with the CBmpImage constructor -- what if loadBmp fails? You have an object that is unusable, but it exists anyway and I don't see where you check for failure of loadBmp so as to prevent usage of the bad object.
Also, instead of this:
Code:
//Objects that will be displayed in the surface
CObjectScene* mObject1;
CObjectScene* mObject2;
CObjectScene* mObject3;
CObjectScene* mObject4;
.... //There's a lot of objects
why not do this for your other code:
Code:
#include <cstdio>
#include <vector>
//...
typedef std::vector<CObjectScene *> ObjectSceneArray;
//...
CImageHandler* mImgHandler;
mImgHandler = new mImgHandler("ImgHandler.cfg");
//...
ObjectSceneArray mObject;
char bufname[30];
for ( int i = 1; i <= whatever_number_of_names; ++i )
{
sprintf( bufname, "Obj%d.cfg", i);
mObject.push_back( new CObjectScene( mImgHandler, bufname ) );
}
//...
Regards,
Paul McKenzie
Re: Porting from VC6 to Linux Fedora core 5 problem
Quote:
Originally Posted by exterminator
This is wrong:
Code:
mObject1 = new CObjectScene(mImgHandler, "Obj1.cfg");
mObject1 = new CObjectScene(mImgHandler, "Obj2.cfg");
mObject1 = new CObjectScene(mImgHandler, "Obj3.cfg");
mObject1 = new CObjectScene(mImgHandler, "Obj4.cfg"); //ERROR here!!!
there are leaks - all memory allocations are lost track of because you are using only one pointer to hold them.. correct it. Why are you not using arrays... Or make a collection class of CObjectScene that takes a vector of filenames and creates those many objects and stores them in a internal container. That would encapsulate all the nasty things that you do in main...
Also, use std::string class for holding strings instead of those C-style character arrays... they will remove cases where manually injecting code can cause errors.
oops sorry. I just copy pasted the line. Actually it didn't quite go like that. The objects were all different. I'll edist my post.
Re: Porting from VC6 to Linux Fedora core 5 problem
Quote:
Originally Posted by g4j31a5
I suspected the :
Code:
mName= new char[strlen(imgname)];
strcpy(mName,imgname);
code because I can't delete the mName in the class's destructor. Anybody can give me some enlightment here? Please???
i'd suspect right
Code:
mName= new char[strlen(imgname)+1];
strcpy(mName,imgname);
mName[strlen(imgname)] = '\0';
strlen returns number of char without null termintor...
Re: Porting from VC6 to Linux Fedora core 5 problem
Quote:
Originally Posted by Paul McKenzie
Here is another problem:
Code:
CImageHandler(char* filename)
{
char imgname[255], filename[255];
You have a parameter called "filename", then you have an array called "filename".
Also, as exterminator pointed out, you can simplify the code greatly if you just stuck with std::string and not introduce char pointers:
Code:
#include <string>
class CBmpImage
{
public:
CBmpImage(const std::string& imgname, const std::string& filename) :
mName( imgname )
{
loadBmp(filename.c_str());
}
private:
std::string mName;
};
You have another problem with the CBmpImage constructor -- what if loadBmp fails? You have an object that is unusable, but it exists anyway and I don't see where you check for failure of loadBmp so as to prevent usage of the bad object.
Also, instead of this:
Code:
//Objects that will be displayed in the surface
CObjectScene* mObject1;
CObjectScene* mObject2;
CObjectScene* mObject3;
CObjectScene* mObject4;
.... //There's a lot of objects
why not do this for your other code:
Code:
#include <cstdio>
#include <vector>
//...
typedef std::vector<CObjectScene *> ObjectSceneArray;
//...
CImageHandler* mImgHandler;
mImgHandler = new mImgHandler("ImgHandler.cfg");
//...
ObjectSceneArray mObject;
char bufname[30];
for ( int i = 1; i <= whatever_number_of_names; ++i )
{
sprintf( bufname, "Obj%d.cfg", i);
mObject.push_back( new CObjectScene( mImgHandler, bufname ) );
}
//...
Regards,
Paul McKenzie
Thanks, I've tried it and it worked. The error is gone. Thank GOD!!! But another problem though (a warning actually), in this code:
Code:
void loadBmp(std:string fullname)
{
if (!(myPic = SDL_LoadBMP(fullName)))
{
printf("ERROR opening file %s\n\n", fullName);
exit(1);
}
}
The printf doesn't work because the parameter is an std::string. Well not that it matters (it's only a warning), but it is somewhat pesky.
Re: Porting from VC6 to Linux Fedora core 5 problem
Quote:
Originally Posted by g4j31a5
The printf doesn't work because the parameter is an std::string. Well not that it matters (it's only a warning), but it is somewhat pesky.
Your code would exhibit undefined behavior, and possibly crash. The "%s" format specifier is looking for a char buffer, and a std::string isn't a char buffer.
You need to use the c_str() member function that returns a const char * in the printf():
Code:
void loadBmp(const std:string& fullname) // Note passed by const reference
{
if (!(myPic = SDL_LoadBMP(fullName)))
{
printf("ERROR opening file %s\n\n", fullName.c_str());
exit(1);
}
}
Also, pass strings by reference (if they are changed within the function) or const reference (if they are not changed in the function). Passing std::string by value (as your code did) may result in a performance hit.
Regards,
Paul McKenzie
Re: Porting from VC6 to Linux Fedora core 5 problem