Dynamic_cast 返回 NULL 但它不应该返回
我有以下类层次结构:
class IStorage {
[...]
}
Q_DECLARE_INTERFACE(IStorage, "ch.gorrion.smssender.IStorage/1.0")
class ISQLiteStorage: public IStorage {
Q_INTERFACES(IStorage)
[...]
}
Q_DECLARE_INTERFACE(ISQLiteStorage, "ch.gorrion.smssender.ISQLiteStorage/1.0")
class DASQLiteStorage: public QObject, public ISQLiteStorage {
Q_OBJECT
Q_INTERFACES(ISQLiteStorage)
[...]
}
我正在使用 QT,并尝试使用 QtPlugin 创建一个插件(为我的应用程序)。 我正在创建 DASQLiteStorage 的一个实例,并将该实例赋予插件中的一个对象:
// the next line is within my main app.
// storage is the DASQLiteStorage instance.
// gateway is an object from within the plugin.
gateway->setDefaultStorage(storage);
// this method lies within the plugin
void AbstractGateway::setDefaultStorage(IStorage* storage) {
defaultStorage_ = dynamic_cast<ISQLiteStorage*>(storage);
}
问题是,在我的主应用程序中执行dynamic_cast 时,dynamic_cast 返回一个空指针(不是预期的)(即在“gateway->setDefaultStorage(storage);”之前)给了我有效的指针(预期)。
有谁知道为什么会发生这种情况?该程序是否在与插件不同的内存范围中运行?这会导致这样的问题吗?有什么想法如何解决这个问题吗?
多谢!
编辑: 我尝试了一些建议:
// this method lies within the plugin
void AbstractGateway::setDefaultStorage(IStorage* storage) {
ISQLiteStorage* s = dynamic_cast<ISQLiteStorage*>(storage);
s = static_cast<ISQLiteStorage*>(storage);
s = qobject_cast<ISQLiteStorage*>((QObject*)storage);
defaultStorage_ = s;
}
在该方法的第一行中, s 等于 NULL,在第二行中 s 包含正确的指针,在第三行中包含另一个指针。为什么这些指针不相等?
为什么尽管我现在正在使用,dynamic_cast 仍然无法工作:
pluginLoader()->setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint);
编辑2: 我注意到,我在代码中进一步得到的分段错误也与此有关。我有以下构造:
// The following classes are defined within the main app.
class ILoginAccount: public IAccount [...]
class AbstractAccountStroageOfficer {
public:
AbstractAccountStroageOfficer(IAccount* account)[...]
}
// These classes are defined within my plugin and are created from within the plugin.
class BCAccount: public ILoginAccount {
public:
BCAccount()
: ILoginAccount(new DAAccountStorageOfficer(this))
{};
}
class DAAccountStorageOfficer: public AbstractAccountStorageOfficer {
public:
DAAccountStorageOfficer(ILoginAccount* account)
: AbstractAccountStorageOfficer(account) // This line raises a segfault.
{
IAccount* a = account; // This line raises a segfault as well.
a = dynamic_cast<IAccount*>(account); // This as well.
a = static_cast<IAccount*>(account); // This as well.
}
}
这些分段错误不应该发生,不是吗?但他们为什么这么做呢?
I'm having the following class hierarchy:
class IStorage {
[...]
}
Q_DECLARE_INTERFACE(IStorage, "ch.gorrion.smssender.IStorage/1.0")
class ISQLiteStorage: public IStorage {
Q_INTERFACES(IStorage)
[...]
}
Q_DECLARE_INTERFACE(ISQLiteStorage, "ch.gorrion.smssender.ISQLiteStorage/1.0")
class DASQLiteStorage: public QObject, public ISQLiteStorage {
Q_OBJECT
Q_INTERFACES(ISQLiteStorage)
[...]
}
I'm using QT and am trying to create a plugin (for my app) with QtPlugin.
I'm creating an instance of DASQLiteStorage and I give this instance to an object FROM WITHIN the plugin:
// the next line is within my main app.
// storage is the DASQLiteStorage instance.
// gateway is an object from within the plugin.
gateway->setDefaultStorage(storage);
// this method lies within the plugin
void AbstractGateway::setDefaultStorage(IStorage* storage) {
defaultStorage_ = dynamic_cast<ISQLiteStorage*>(storage);
}
The problem is, that the dynamic_cast is returning me a null-pointer (not expected), while doing the dynamic_cast within my main app (i.e. before "gateway->setDefaultStorage(storage);") gives me the valid pointer (expected).
Does anyone know why this could happen? Is the program operating in a different memory range as the plugin? Could this lead to such problems? Any ideas how to fix this?
Thanks a lot!
EDIT:
I've tried out some suggestions:
// this method lies within the plugin
void AbstractGateway::setDefaultStorage(IStorage* storage) {
ISQLiteStorage* s = dynamic_cast<ISQLiteStorage*>(storage);
s = static_cast<ISQLiteStorage*>(storage);
s = qobject_cast<ISQLiteStorage*>((QObject*)storage);
defaultStorage_ = s;
}
In the first line of the method, s equals NULL, in the second s contains the correct pointer and in the third an other pointer. Why aren't these pointers equal?
And why could the dynamic_cast be still not working although I'm using now:
pluginLoader()->setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint);
EDIT2:
I noticed, that the segmentation fault I get a little further in the code is also related to this. I have the following construct:
// The following classes are defined within the main app.
class ILoginAccount: public IAccount [...]
class AbstractAccountStroageOfficer {
public:
AbstractAccountStroageOfficer(IAccount* account)[...]
}
// These classes are defined within my plugin and are created from within the plugin.
class BCAccount: public ILoginAccount {
public:
BCAccount()
: ILoginAccount(new DAAccountStorageOfficer(this))
{};
}
class DAAccountStorageOfficer: public AbstractAccountStorageOfficer {
public:
DAAccountStorageOfficer(ILoginAccount* account)
: AbstractAccountStorageOfficer(account) // This line raises a segfault.
{
IAccount* a = account; // This line raises a segfault as well.
a = dynamic_cast<IAccount*>(account); // This as well.
a = static_cast<IAccount*>(account); // This as well.
}
}
These segmentation faults should not occur, should they? But why do they?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
基本上,RTTI 在跨模块边界时是不可靠的。不同的编译器在这里有不同的行为;您必须研究您的编译器/版本在这种情况下的行为。当然,如果您的主应用程序和插件有不同的编译器/版本,那么它显然没有机会工作。
使用 static_cast 作为解决方法。
Basically, RTTI is unreliable across module boundaries. Different compilers have different behaviors here; you'll have to research how your compiler/version acts in this case. Of course, if you have a different compiler/version for the main app and plugin, it clearly has no chance of working.
Use static_cast as a work around.