是否需要删除动态结构内容,然后删除结构本身?

时间:2015-05-17 22:19:49

标签: c++ memory-management

*** Error in `./out': munmap_chunk(): invalid pointer: 0x0000000000400824 ***

给我以下错误:

extern crate rustc_serialize;
use rustc_serialize::json::Json;
use std::fs::File;
use std::io::copy;
use std::io::stdout;

fn main() {
    let mut file = File::open("text.json").unwrap();
    let mut stdout = stdout();
    let mut str = &copy(&mut file, &mut stdout).unwrap().to_string();
    let data = Json::from_str(str).unwrap();
}

我的问题是,删除bread->名称是否甚至是必要的,或者如果删除面包会为我处理。如果有必要删除bread->名称,为什么程序会在我尝试执行时崩溃?

2 个答案:

答案 0 :(得分:8)

问题实际上源于此:

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";

答案 1 :(得分:3)

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;
}

基本上,您使用new char[6]的常量char数组覆盖动态分配的char数组"bread"。删除动态分配,您不必删除它。

当您编写"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 \0 (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 ++中完成所有这些。