联系
Knight's Tale » 技术

Don't use "memset" function for you "std::string" objects! (Memory Leaks Error)

2010-06-02 15:47

Today I meet a memory leaks error in my program and I always cannot find the place where memory leaks happen.  Though I use MS Memory Leaks Detect Tricks, it doesn't help. This is because STL memory leaks cann't be found by this trick, I think. I almost spent half day to find the solution, so I'll write down this problem and the solution for you and me.

About two months ago, I wrote a Material Class for Obj format model:

class Material
{
public:
    Material(){ setDefaults();}
    void setDefaults(){ memset(this,0,sizeof(*this));}
    int mark;
    char materialName[256]; // material name
    Vector3 ambient;    // ambient
    Vector3 diffuse;    // diffuse
    Vector3 specular;   // specular
    int shininess;  //
    float alpha;    //
    bool isSpecular;

char textureName[256];  // texture name
char textureTransName[256]; // transparent texture name

};

As we all know, the above codes runs good. It uses C-style initialize method "memset" to set class attributes to be zero. But today, I want to reuse these codes with C++ style, so I rewrite the codes:
class Material
{
public:
    Material(){ setDefaults();}
    void setDefaults(){ memset(this,0,sizeof(*this));}
    int mark;
    std::string materialName;   // material name
    Vector3 ambient;    // ambient
    Vector3 diffuse;    // diffuse
    Vector3 specular;   // specular
    int shininess;  //
    float alpha;    //
    bool isSpecular;

std::string textureName;    // texture name
std::string textureTransName;   // transparent texture name

};

Do you think these codes are ok for my progam? NO!, if you use this class in your project, you will have Memory Leaks! and you will never know the problem is caused by this class. You will get errors as follows:

3{235250} normal block at 0x01774A60, 16 bytes long. 4 Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 5{235237} normal block at 0x01774CB0, 16 bytes long. 6 Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 7{235234} normal block at 0x01774A10, 16 bytes long. 8 Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

The reason why this problem occurs is that you use C-style initialize method "memset" for C++ object "std::string". Please never use memset in your new C++ program which struct/class has C++ objects ( such as vector, string objects ).

So, the solution is that you should initialize the variable manually with C++ style.

class Material
{
public:
    Material(){ setDefaults();}
    void setDefaults()
        {
        this->ambient = Vector3( 0.2f, 0.2f, 0.2f );
        this->diffuse = Vector3( 0.8f, 0.8f, 0.8f );
        this->specular = Vector3( 1.0f, 1.0f, 1.0f );
        this->shininess = 0;
        this->alpha = 1.0f;
        this->isSpecular = false;
        this->textureName = "";
        this->textureTransName = "";
        this->mark = 0;
        }
    int mark;
    std::string materialName;   // material name
    Vector3 ambient;    // ambient
    Vector3 diffuse;    // diffuse
    Vector3 specular;   // specular
    int shininess;  //
    float alpha;    //
    bool isSpecular;

std::string textureName;    // texture name
std::string textureTransName;   // transparent texture name

};

Good Luck for you!

Reference:

[1].  http://www.cppblog.com/qinqing1984/archive/2009/08/07/92479.html