有必要删除动态结构内容,然后删除结构本身吗?
Necessary to delete dynamic struct contents, and then the struct itself?
#include <cstring>
using namespace std;
struct Product {
char * name;
float price;
};
int main() {
Product * bread = new Product;
bread->name = new char[6];
bread->name = "bread";
delete[] bread->name; //!!!THE ERROR OCCURS ON THIS LINE!!!
delete bread;
}
给我以下错误:
*** Error in `./out': munmap_chunk(): invalid pointer: 0x0000000000400824 ***
我的问题是是否有必要删除 bread->name,或者删除 bread 是否会为我解决这个问题。如果需要删除 bread->name,为什么当我尝试这样做时程序会崩溃?
其实问题出在这里:
bread->name = "bread";
为 name
分配一个新数组后,您将该指针分配给一个完全不同的值 - 一个恰好存在于只读内存中的值。因此,当您删除它时会出现错误:您正在尝试 delete []
一个您未分配的数组。
关键问题是你不想分配指针 name
,你想填充刚刚分配的数组的内容——你想要填充 name
指向 的内容。为此,strcpy
:
strcpy(bread->name, "bread");
或者真的,因为这是 C++:
struct Product {
std::string name;
float price;
};
Product bread;
bread.name = "bread";
int main() {
Product * bread = new Product;
bread->name = new char[6];
bread->name = "bread"; // <- Error! Overwriting the pointer value!
delete[] bread->name; // <- Error! Trying to free read-only memory where "bread" is stored...
delete bread;
}
基本上,您是用 "bread"
的常量字符数组覆盖动态分配的字符数组 new char[6]
。去掉动态分配就不用删了
当您编写 "bread"
时,编译器会获取这些字母并将它们存储在只读存储器中。每次你写 "bread"
并尝试分配它时,你实际上是在分配一个指向只读内存的指针,或者一个 const char*
.
当您分配动态数组时,您将动态分配内存的地址存储在 bread->name
指针中,但随后您用 只读内存的地址覆盖了它不允许免费。因此编译器抱怨它。
在您的代码中,由于您不再拥有指向动态分配内存的指针,new char[6]
,您将无法再释放它,并且还会发生内存泄漏。
我会这样做(考虑到您对使用字符串的限制)并假设您真的想要动态分配:
int main() {
const char* breadStr = "bread";
int len = strlen(breadStr);
Product * bread = new Product;
bread->name = new char[len + 1];
strncpy(bread->name, breadStr, len + 1); // Copy the string and the [=11=] (hence the +1)
delete[] bread->name; // no more error!
delete bread;
}
如果不需要动态分配,那么您可以这样做:
int main() {
Product * bread = new Product;
bread->name = "bread";
// You don't have to delete the bread->name since it is NOT dynamically allocated but is in your read-only memory.
delete bread;
}
但我真的更愿意使用@Barry 建议的字符串在 C++ 中完成所有这些操作。
#include <cstring>
using namespace std;
struct Product {
char * name;
float price;
};
int main() {
Product * bread = new Product;
bread->name = new char[6];
bread->name = "bread";
delete[] bread->name; //!!!THE ERROR OCCURS ON THIS LINE!!!
delete bread;
}
给我以下错误:
*** Error in `./out': munmap_chunk(): invalid pointer: 0x0000000000400824 ***
我的问题是是否有必要删除 bread->name,或者删除 bread 是否会为我解决这个问题。如果需要删除 bread->name,为什么当我尝试这样做时程序会崩溃?
其实问题出在这里:
bread->name = "bread";
为 name
分配一个新数组后,您将该指针分配给一个完全不同的值 - 一个恰好存在于只读内存中的值。因此,当您删除它时会出现错误:您正在尝试 delete []
一个您未分配的数组。
关键问题是你不想分配指针 name
,你想填充刚刚分配的数组的内容——你想要填充 name
指向 的内容。为此,strcpy
:
strcpy(bread->name, "bread");
或者真的,因为这是 C++:
struct Product {
std::string name;
float price;
};
Product bread;
bread.name = "bread";
int main() {
Product * bread = new Product;
bread->name = new char[6];
bread->name = "bread"; // <- Error! Overwriting the pointer value!
delete[] bread->name; // <- Error! Trying to free read-only memory where "bread" is stored...
delete bread;
}
基本上,您是用 "bread"
的常量字符数组覆盖动态分配的字符数组 new char[6]
。去掉动态分配就不用删了
当您编写 "bread"
时,编译器会获取这些字母并将它们存储在只读存储器中。每次你写 "bread"
并尝试分配它时,你实际上是在分配一个指向只读内存的指针,或者一个 const char*
.
当您分配动态数组时,您将动态分配内存的地址存储在 bread->name
指针中,但随后您用 只读内存的地址覆盖了它不允许免费。因此编译器抱怨它。
在您的代码中,由于您不再拥有指向动态分配内存的指针,new char[6]
,您将无法再释放它,并且还会发生内存泄漏。
我会这样做(考虑到您对使用字符串的限制)并假设您真的想要动态分配:
int main() {
const char* breadStr = "bread";
int len = strlen(breadStr);
Product * bread = new Product;
bread->name = new char[len + 1];
strncpy(bread->name, breadStr, len + 1); // Copy the string and the [=11=] (hence the +1)
delete[] bread->name; // no more error!
delete bread;
}
如果不需要动态分配,那么您可以这样做:
int main() {
Product * bread = new Product;
bread->name = "bread";
// You don't have to delete the bread->name since it is NOT dynamically allocated but is in your read-only memory.
delete bread;
}
但我真的更愿意使用@Barry 建议的字符串在 C++ 中完成所有这些操作。