这是另一个,“我的代码不工作,我不知道为什么,”我害怕的问题。我只是没有足够的知识stl知道为什么std :: map :: insert会引发异常。如果你知道什么情况会引发异常,你可以跳过这段文字并回答。如果你迫切需要关于这个问题的一些背景知识,那么就对它有所了解。我会发布我的代码并解释所做的事情,如果您对stl有更深入的了解,可以解释我插入的电话会出现什么问题,我将非常感激。std :: map :: insert exception
我前一段时间写过一个对象,偶尔用作我的工厂对象。它的主要目的基本上是取一个字符串并存储字符串和一个“创建新的对象函数”指针,这样最终可以调用一个函数,传递一个字符串,并且如果有一个有效的注册,它会返回派生对象的新实例。少说话,更多的代码,这里就是我的了:这里
factory.h
#ifndef FACTORY_H
#define FACTORY_H
// library tools
#include <map>
#include <string>
// Simplified registration macros
#define DECLARE_DERIVED(T, base) static Factory<base>::DerivedRegister<T> reg;
#define DEFINE_DERIVED(T, base, s) Factory<base>::DerivedRegister<T> T::reg(s);
template<class base>
class Factory
{
protected:
template<class T>
static base * createT() { return new T;}
public:
typedef std::map<std::string, base*(*)()> map_type;
virtual ~Factory(){ }
static base * createInstance(const std::string & s)
{
if(!m_Map.count(s))
return nullptr;
std::map<std::string, base*(*)()>::iterator it = m_Map.find(s);
return it->second();
}
template <class T>
struct DerivedRegister;
protected:
static map_type m_Map;
};
template<class base>
template<class T>
struct Factory<base>::DerivedRegister : public Factory<base>
{
DerivedRegister(std::string const & s)
{
m_Map.insert(std::pair<std::string, base*(*)()>(s, &createT<T>));
}
};
#endif
是什么它真正的快速更好的解释。假设你有一个基类,A类。然后你有任何数量的派生类。我将某个工厂对象放在模板化为A的某处,然后手动创建一个派生的注册对象,或者使用派生类声明中顶部的宏来创建一个静态注册表对象。然后在实现中定义它,并将其称为构造函数,传递一个字符串用于标识对象。使用工厂成员createInstance,您可以传递一个字符串标识符并具有返回的派生对象,由A *指向。
例如:
A.H
class A
{
};
A.cpp
// the map for this factory template has to be defined somewhere, as it is static
Factory<A>::map_type Factory<A>::m_Map;
b.h
#include <A.h>
class B : public A
{
// anywhere in declaration of derived B
DECLARE_DERIVED(A, B)
};
b.cpp
// just somewhere in cpp file
DEFINE_DERIVED(A, B, "B")
的main.cpp
int main()
{
A * ptr;
Factory<A> factory;
ptr = factory.createInstance("B");
}
此目的为我工作在过去,大多顺利。现在我正在做一个更复杂一点的项目。我喜欢参与游戏引擎的数据组织/ api设计,我只是试图实现一个编目方案(但没有实例化)着色器的解决方案,这样你就可以得到一个完整的着色器列表,已编程,但它们不会在运行时实例化,除非需要。除此之外,这个问题实际上与d3d11无关,或者至少我不希望。
所以这里是发生了什么事。我有一个代表图形着色器抽象类的对象。所有你想写的着色器必须来自这个对象。您从所有不同着色器派生并实现它的功能是不同的。我们在名称空间同步和派生着色器“ColorShader”“LightShader”和“TextureShader”中调用基础对象“SYNC :: D3D11Shader”。因为我不是简单地想在渲染对象内制作这些着色器实例的std :: map,所以我在渲染对象内创建了一个工厂。
D3D11Renderer。ħ
class D3D11Renderer
{
// many other members...
Factory<D3D11Shader> m_ShaderFactory;
// many other member...
};
D3D11Renderer.cpp
// define this templated classes map or you'll get undefined errors
Factory<SYNC::D3D11Shader>::map_type Factory<SYNC::D3D11Shader>::m_Map;
,然后在ColorShader我使用宏像这样
D3D11ColorShader.h
class D3D11ColorShader : public SYNC::D3D11Shader
{
// ...lotsa members
DECLARE_DERIVED(D3D11ColorShader, SYNC::D3D11Shader)
// lotsa member...
};
D3D11ColorShader.cpp
// define the registery object with it's key here
DEFINE_DERIVED(D3D11ColorShader, SYNC::D3D11Shader, "ColorShader")
这一切都编译得很好,并且它引发异常的地方是我首先调用D3D11ColorShader.cpp中的registryObjects构造函数,特别是在插入调用时。异常错误是这样的:0000005:访问 冲突读取位置0x00000004
在0x772315de在Syncopate.exe未处理的异常。
所以在现实中,问题归结为什么时候std :: map :: insert引发异常以及为什么。我只知道每个人都会问我在做什么的背景。低下,看到一个巨大的文字墙出现了!我真正需要的是一种预感。
也应该我还是应该不标记d3d11,因为这个问题并不真正属于它?
我没有阅读整篇文章,但访问冲突通常意味着取消引用空指针 – shengy
@shengy - yup,但事情是,工厂内的std :: map不是指针。我从来没有创建一个新的地图或删除它:\。所以什么时候它会产生一个异常,map不是一个指针?如果未定义,它会引发编译错误:\。 – FatalCatharsis
它不会引发异常。在代码的任何地方都没有'throw',无论是你的还是图书馆。运行时系统(操作系统,用于所有实际目的)都想告诉程序它是borken,并且这有一个例外的形式。在某个地方你有一个糟糕的指针(数据损坏),并且这可能导致访问违规,可能会或可能不会接近腐败点。 –