最近遇到了c++几张内存错误的几种典型情况:
1. 拷贝构造函数导致重复释放:http://blog.csdn.net/winlinvip/article/details/7663862
2. 内存越界导致错误:这个在http://blog.csdn.net/winlinvip/article/details/7822762 提到过。
3. 非虚析构函数导致内存泄漏:http://blog.csdn.net/winlinvip/article/details/7667460
4. 局部数组越界导致栈错误:http://blog.csdn.net/winlinvip/article/details/7822762 稍微提了一下。
把重现它们的代码集中放到这里:
1. 拷贝构造函数导致重复释放
- #include <string.h>
- #include <iostream>
- using namespace std;
- class MyString
- {
- private:
- int length;
- char* value;
- public:
- MyString(const char* str = NULL){
- length = 0;
- value = NULL;
- SetString(str);
- }
- ~MyString(){
- delete[] value;
- }
- public:
- void SetString(const char* str){
- if(str != NULL){
- length = strlen(str);
- value = new char[length + 1];
- memcpy(value, str, length);
- value[length] = 0x00;
- }
- }
- public:
- const char* GetString(){
- return (const char*)value;
- }
- };
- int main(){
- MyString str("winlin");
- str = "hello world";
- cout << "expect: hello world, actual: " << str.GetString() << endl;
- sleep(5);
- return 0;
- }
#include <string.h>
#include <iostream>
using namespace std;
class MyString
{
private:
int length;
char* value;
public:
MyString(const char* str = NULL){
length = 0;
value = NULL;
SetString(str);
}
~MyString(){
delete[] value;
}
public:
void SetString(const char* str){
if(str != NULL){
length = strlen(str);
value = new char[length + 1];
memcpy(value, str, length);
value[length] = 0x00;
}
}
public:
const char* GetString(){
return (const char*)value;
}
};
int main(){
MyString str("winlin");
str = "hello world";
cout << "expect: hello world, actual: " << str.GetString() << endl;
sleep(5);
return 0;
}
2. 内存越界导致错误
- /**
- # build the gperftools:
- bash build_gperftools.memory-fence.sh
- # to build:
- g++ -g -O0 -c memcorrupt.cpp -o memcorrupt.o -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free; g++ memcorrupt.o -o memcorrupt -ltcmalloc_debug; ./memcorrupt
- */
- #include <stdio.h>
- class Connection;
- class State
- {
- private:
- Connection* conn;
- public:
- State(Connection* c) : conn(c){
- }
- virtual ~State(){
- }
- void action();
- };
- class Manager;
- class Connection
- {
- private:
- State* state;
- Manager* manager;
- public:
- Connection(){
- state = NULL;
- }
- virtual ~Connection(){
- if(state != NULL){
- delete state;
- state = NULL;
- }
- }
- public:
- void SetManager(Manager* m){
- manager = m;
- }
- Manager* GetManager(){
- return manager;
- }
- void SetState(State* s){
- state = s;
- }
- };
- class Manager
- {
- private:
- Connection* conn;
- public:
- Manager(){
- conn = NULL;
- }
- virtual ~Manager(){
- }
- public:
- void Destroy(){
- if(conn != NULL){
- delete conn;
- conn = NULL;
- }
- }
- Connection* GetConnection(){
- return conn;
- }
- void SetConnection(Connection* c){
- conn = c;
- conn->SetManager(this);
- }
- };
- void State::action(){
- if(conn == NULL){
- return;
- }
- conn->GetManager()->Destroy();
- this->conn = NULL;
- }
- int main(int /*argc*/, char** /*argv*/){
- Manager manager;
- Connection* connection = new Connection();
- State* state = new State(connection);
- connection->SetState(state);
- manager.SetConnection(connection);
- state->action();
- return 0;
- }
/**
# build the gperftools:
bash build_gperftools.memory-fence.sh
# to build:
g++ -g -O0 -c memcorrupt.cpp -o memcorrupt.o -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free; g++ memcorrupt.o -o memcorrupt -ltcmalloc_debug; ./memcorrupt
*/
#include <stdio.h>
class Connection;
class State
{
private:
Connection* conn;
public:
State(Connection* c) : conn(c){
}
virtual ~State(){
}
void action();
};
class Manager;
class Connection
{
private:
State* state;
Manager* manager;
public:
Connection(){
state = NULL;
}
virtual ~Connection(){
if(state != NULL){
delete state;
state = NULL;
}
}
public:
void SetManager(Manager* m){
manager = m;
}
Manager* GetManager(){
return manager;
}
void SetState(State* s){
state = s;
}
};
class Manager
{
private:
Connection* conn;
public:
Manager(){
conn = NULL;
}
virtual ~Manager(){
}
public:
void Destroy(){
if(conn != NULL){
delete conn;
conn = NULL;
}
}
Connection* GetConnection(){
return conn;
}
void SetConnection(Connection* c){
conn = c;
conn->SetManager(this);
}
};
void State::action(){
if(conn == NULL){
return;
}
conn->GetManager()->Destroy();
this->conn = NULL;
}
int main(int /*argc*/, char** /*argv*/){
Manager manager;
Connection* connection = new Connection();
State* state = new State(connection);
connection->SetState(state);
manager.SetConnection(connection);
state->action();
return 0;
}
3. 非虚析构函数导致内存泄漏
- /**
- g++ -g -O0 use-interface.cpp -o use-interface; ./use-interface
- */
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- class IObject
- {
- public:
- virtual const char* ToString() = 0;
- };
- class String : public IObject
- {
- private:
- char* str;
- public:
- String(const char* s){
- str = NULL;
- if(s != NULL){
- str = new char[strlen(s) + 1];
- strcpy(str, s);
- }
- }
- virtual ~String(){
- if(str != NULL){
- delete[] str;
- }
- }
- public:
- virtual const char* ToString(){
- return str;
- }
- };
- void destroy(IObject* obj){
- delete obj;
- }
- int main(int /*argc*/, char** /*argv*/){
- while(true){
- destroy(new String("winlin"));
- usleep(1);
- }
- return 0;
- }
/**
g++ -g -O0 use-interface.cpp -o use-interface; ./use-interface
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
class IObject
{
public:
virtual const char* ToString() = 0;
};
class String : public IObject
{
private:
char* str;
public:
String(const char* s){
str = NULL;
if(s != NULL){
str = new char[strlen(s) + 1];
strcpy(str, s);
}
}
virtual ~String(){
if(str != NULL){
delete[] str;
}
}
public:
virtual const char* ToString(){
return str;
}
};
void destroy(IObject* obj){
delete obj;
}
int main(int /*argc*/, char** /*argv*/){
while(true){
destroy(new String("winlin"));
usleep(1);
}
return 0;
}
4. 局部数组越界导致栈错误
- /**
- g++ -g -O0 stack-corrupt.cpp -o stack-corrupt; ./stack-corrupt
- */
- #include <stdio.h>
- #include <string.h>
- void packet_unmarshal(char* stream, int size){
- printf("memcpy, size=%d\n", size);
- // decode packet from stream.
- char data[100];
- memcpy(data, stream, size);
- printf("memcpy finished\n");
- }
- void normal_opration3(){
- char stream[116];
- packet_unmarshal(stream, sizeof(stream));
- printf("normal opration3\n");
- }
- void normal_opration2(){
- normal_opration3();
- printf("normal opration2\n");
- }
- void normal_opration1(){
- normal_opration2();
- printf("normal opration1\n");
- }
- void normal_opration(){
- normal_opration1();
- printf("normal opration\n");
- }
- int main(int /*argc*/, char** /*argv*/){
- normal_opration();
- return 0;
- }