我一直在编写一个测试用例程序来演示我的一个更大程序的问题, 并且测试用例有一个原始程序没有的错误。
这是头文件:
// compiled with g++ -I/usr/local/bin/boost_1_43_0 -Wall -std=c++0x -g test.cpp
#include <bitset>
#include <boost/shared_ptr.hpp>
#include <vector>
typedef std::vector< std::vector< std::bitset<11> > > FlagsVector;
namespace yarl
{
namespace path
{
class Pathfinder;
}
namespace level
{
class LevelMap
{
// Member Variables
private:
int width, height;
FlagsVector flags;
public:
boost::shared_ptr<path::Pathfinder> pathfinder;
// Member Functions
LevelMap(const int, const int);
int getWidth() const {return width;}
int getHeight() const {return height;}
bool getFifthBit(const int x, const int y) const
{
return flags.at(x).at(y).test(5);
}
};
class Level
{
// Member Variables
public:
LevelMap map;
// Member Functions
public:
Level(const int w=50, const int h=50);
};
}
namespace path
{
class Pathfinder
{
// Member Variables
private:
boost::shared_ptr<level::LevelMap> clientMap;
// Member Functions
public:
Pathfinder() {}
Pathfinder(level::LevelMap* cm)
: clientMap(cm) {}
void test() const;
};
}
}
这是实现文件:
#include <iostream>
#include "test.hpp"
using namespace std;
namespace yarl
{
namespace level
{
LevelMap::LevelMap(const int w, const int h)
: width(w), height(h), flags(w, vector< bitset<11> >(h, bitset<11>())),
pathfinder(new path::Pathfinder(this))
{}
Level::Level(const int w, const int h)
: map(w,h)
{
map.pathfinder->test();
}
}
namespace path
{
void Pathfinder::test() const
{
int width = clientMap->getWidth();
int height = clientMap->getHeight();
cerr << endl;
cerr << "clientMap->width: " << width << endl;
cerr << "clientMap->height: " << height << endl;
cerr << endl;
for(int x=0; x<width; ++x)
{
for(int y=0; y<height; ++y)
{
cerr << clientMap->getFifthBit(x,y);
}
cerr << "***" << endl; // marker for the end of a line in the output
}
}
}
}
int main()
{
yarl::level::Level l;
l.map.pathfinder->test();
}
我将此程序与电围栏链接,当我运行它时,它因以下错误而中止:
ElectricFence Aborting: free(bffff434): address not from malloc().
Program received signal SIGILL, Illegal instruction.
0x0012d422 in __kernel_vsyscall ()
gdb 的回溯显示非法指令在编译器生成的 Pathfinder
析构函数中,它在析构其 shared_ptr 时遇到问题。有人知道这是为什么吗?
最佳答案
yarl::level::Level l;
您实例化一个自动 Level
变量,它在其构造函数中构造其成员 pathfinder
,如下所示:
pathfinder(new path::Pathfinder(this))
然后在 Pathfinder
构造函数中,它获取您传入的 Level
指针并将其分配给 shared_ptr
。 shared_ptr
然后获得该指针的所有权。
由于以下几个原因,这是不正确的:
shared_ptr
应该用于管理动态分配的对象,而不是自动分配的对象- 如果你想使用
shared_ptr
,那么你应该在任何地方都使用它:就像现在一样,你传递原始指针(例如传递给Pathfinder
的构造函数,但是随后将它们存储为shared_ptr
。这只会打开一大堆所有权蠕虫病毒。 - 将
this
分配给shared_ptr
的正确方法是派生自enable_shared_from_this
;但是请注意,您无法在构造函数中从this
获取shared_ptr
。
当 shared_ptr
被销毁时,它会尝试删除它管理的指针。然而,在这种情况下,该指针不是指向动态分配的对象(即,使用 new
分配),而是指向自动分配的对象(即,在堆栈上)。因此,错误。
如果您不需要某些东西来获取资源的所有权,那么使用原始指针(或引用,如果您有该选项)没有任何问题。
关于c++ - "address not from malloc()"使用电子围栏出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3330629/