2010-06-21 28 views
2

我是C++的新手,在正在编写的类中正确使用映射时遇到了问题。基本上,当我在一个测试程序中创建一个新的Block对象并调用它的写入方法时,该程序完全不合格,给我一个双重释放或损坏错误。奇怪的是,如果我在Block构造函数中取消注释一行,那么一切正常。我猜我缺少一些基本的C++知识,但我在google上找不到任何有用的东西。我在做什么错误的c + +地图? (可怕的内存错误)

Block.h(包括不显示,但它们的存在):

namespace SSDSim{ 
    class Block{ 
     public: 
      Block(uint block_num); 
      ~Block(void); 
      void read(uint page_num); 
      void write(uint page_num, void *data); 
      void erase(void); 
     private: 
      uint block_num; 
      std::map<uint, void *> page_data; 
    }; 
} 

Block.cpp:

#include "Block.h" 

using namespace std; 
using namespace SSDSim; 

Block::Block(uint block){ 
    //page_data[4]= (void *) 0xfeedface; 
    block_num= block; 
} 

... 

void Block::write(uint page_num, void *data){ 
    if (page_data.find(page_num) == page_data.end()){ 
     page_data[page_num]= data; 
    } else{ 
     cerr<<"Invalid write\n"; 
     exit(1); 
    } 
} 

TEST.CPP:

#include <iostream> 
#include "../Block.h" 

using namespace std; 
using namespace SSDSim; 

int main(void){ 
    Block b= Block(0); 
    b.write(0, (void *) 0xdeadbeef); 
    b.read(0); 
// b.read(4); 
    return 0; 
} 
+0

只是一个挑剔,但你应该避免使用诸如“../Block.h”的相对路径。当代码被移动或稍后有人来阅读代码时,这最终导致很多麻烦。将路径相对于存储库根目录相对较好通常会更好。大多数编译器允许您将位置添加到包含搜索路径。有了gcc,你可以使用-Ipath/to/root,然后让include文件引用相对于该位置的内容。 – 2010-06-21 17:28:39

+0

'Block :: read'和'Block'的析构函数是做什么的? – 2010-06-21 17:31:22

+0

你正在使用'void *',这很可怕... – 2010-06-21 19:04:56

回答

2

你确定错误是不是当你打电话read()?毕竟,您的构造函数将page[4]指定为0xfeedface,这是指向任何内容的内存中的任意位置。如果您尝试在内存中读取该位置,可能会发生不好的事情。

我会尽量避免创建任意地址的指针。相反,通过制作一些对象并将其地址传递给page[4]来测试您的程序。

错误也可能在你的析构函数中。由于您在堆栈上分配了Block,因此在析构函数超出范围时会调用它。

+0

是的,我确定。我试过没有任何读取的情况下运行该程序。实际上,我在write()中将问题追踪到一行: page_data [page_num] = data; 可能应该包括在原来的职位......哎呀。 另外。我从来没有真正遵守或试图释放我在地图上存储的空指针。 – 2010-06-21 17:24:04

+0

您是否尝试过使用相同的方法,但是使用“新块”而不是使用堆栈?错误可能在你的析构函数中。 – 2010-06-21 17:25:20

+0

人。谢谢。错误在我的析构函数中。在我继续编写代码之前,我应该多读一点C++。是否有一个特定的原因,为什么析构函数会搞砸其他功能? – 2010-06-21 17:35:04

0

您需要显示为Block::read()的代码,但我认为这是你正在试图访问该项目从获得来自map元素与关键4返回时,有在地图上没有这样的元素一个安全的赌注。

(您的注释行增加了一个,所以它在这种情况下起作用)。

1

很难说出什么问题,因为你显示的代码太少。

然而,Rule Of Three说,当一个类有两种析构函数,拷贝构造函数或赋值操作符,那么它很可能需要他们三个。
考虑到这一点,你的SSDSim::Block类看起来非常可疑。那个析构函数需要做什么,但不需要照顾复制?

+0

是的。正如我所提到的,我对C++很陌生,因为我现在不得不对这个项目进行一点小小的调整,所以我现在处于困境中。你的问题的答案是它可能不需要析构函数,我需要花更多时间熟悉C++。 – 2010-06-21 17:46:22

+1

@Peter:一本非常好的初学者书是由Koenig和Moo编写的__Accelerated C++ __。它有一个陡峭的学习曲线,但设法将几乎所有的基本C++知识打包到250页。它的主要优势在于它可以教会编写好的,安全的高级C++的正确习惯用法。如果你喜欢它更详细的,有Lippman等人的C++ Primer__。看看[The Definitive C++ Book List and Guide](http://stackoverflow.com/questions/388242)。 – sbi 2010-06-21 17:58:08

+0

感谢您的阅读建议。我会尽力让我的手迅速加速C++。 – 2010-06-21 18:03:31