发生了缓冲区溢出

时间:2014-03-16 12:29:31

标签: c++ qt qobject

几天前,为了安全起见,我公司将操作系统从Windows XP改为Windows 7(32位)。

我在VS 2008,QT 4.8.1和Boost中使用C ++。我的应用程序中的Struct Member Alignment是1个字节(/ Zp1)。

更改后,我发现了一个错误:

我加载了使用QPluginLoader创建的库,然后使用qobject_cast将其转换为我的界面。在我的图书馆里,我可能会加载另一个。

当我在操作系统更改后在调试模式下测试我的应用程序时,一切正常。一切都像它想象的那样工作,然后我将它改为Release并且我的应用程序开始崩溃。

当我使用VS 2008调试它时,我看到了这个错误:

  

my_app.exe中发生了缓冲区溢出,该程序已损坏程序的内部状态。按Break打开调试程序或继续终止程序。

     

有关详细信息,请参阅帮助主题“如何调试缓冲区溢出问题”。

该应用程序在Windows XP(发布和调试模式)下仍能正常运行。

一开始,我认为这是因为依赖或我错过了什么。通过登录发布模式测试和跟踪我的应用程序几个小时后,我终于发现了什么是错的。当一个方法试图将值(任何东西)返回给在库中调用它的另一个方法时,我的应用程序崩溃了。

例如:

方法B返回Bool,我在方法A中调用它。当方法B完成并准备将Bool值返回给方法A时,wy应用程序崩溃。如果方法返回值,它也会在想要返回加载库的方法时崩溃。不知何故,使用不返回任何值(void)的方法就可以了。

为了确定什么是错误的,我的方法中的代码,我做了另一个应用程序(测试人员)并开始逐个添加我的代码以找到错误。我相信这与QT有关。

请检查以下代码并告诉我您是否知道错误。

我有main.cpp加载这样的插件:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString filename = "correct path";

    QPluginLoader* pluginLoader = new QPluginLoader(filename);

    QObject *plugin = pluginLoader->instance();

    PluginInterface* plugin_instance;

    if (plugin) 
    {

        SecureZeroMemory(&plugin_instance, sizeof(PluginInterface));

        plugin_instance = qobject_cast<PluginInterface *>(plugin);

    }

    bool result = plugin_instance->initialize();

    return a.exec();
}

这是我的界面:

class PluginInterface
{
public:

    virtual bool initialize() = 0;
};

QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(PluginInterface,"some text");
QT_END_NAMESPACE

我像这样制作我的图书馆:

plugin.hpp

class Plugin : public QObject, public PluginInterface
{
    Q_OBJECT
    Q_INTERFACES(PluginInterface)

public:
    Plugin();
    bool initialize();  
};

plugin.cpp

#define SUPPORTED_VERSIONS  0x01011403
#define WFS_TRACE_NONE      0

bool Plugin::initialize()
{
    WFSVERSION wfs_version;
    HRESULT hRes;

    cout << "WFSStartUp" << endl;

    hRes = WFSStartUp(SUPPORTED_VERSIONS, &wfs_version);

    WORD version = wfs_version.wVersion;

    cout << "version : " << version << endl;

    DWORD dwTrace = WFS_TRACE_NONE;

    cout << "WFSCreateAppHandle" << endl;

    HRESULT hRes2;
    HANDLE app_handle;
    hRes2 = WFSCreateAppHandle(&app_handle);

    cout << "Result : " << hRes2 << endl;

    return true;
}
Q_EXPORT_PLUGIN2(my_plugin, Plugin);

这是我的测试人员应用程序的输出:

  

WFSStartUp
  版本:63424
  WFSCreateAppHandle
  结果:0
  申请崩溃!!

Plugin::initialize()内的代码运行正常。我将其复制/粘贴到main()并运行应用程序以确定它。

这里有什么问题?我错过了什么?

3 个答案:

答案 0 :(得分:1)

此代码:

PluginInterface* plugin_instance;

if (plugin) 
{

    SecureZeroMemory(&plugin_instance, sizeof(PluginInterface));

    plugin_instance = qobject_cast<PluginInterface *>(plugin);

}
如果SecureZeroMemory做了它的名字所说的话,那么

将导致崩溃。

要将指针归零,只需将其设置为0.

但是,另外要提到的是,当您接下来要做的事情是分配给它时,无意义,如上所述。

答案 1 :(得分:1)

  

我已经在没有SecureZeroMemory的情况下进行了测试,但它仍然崩溃,SecureZeroMemery不是导致崩溃的原因!

很可能在代码的其他地方还有其他类似的错误 - 你不会显示的地方。

至少,您是在使用相同的编译器编译应用程序中的所有(所有库,DLL等),并使用相同的设置吗?如果你使用&#34; / Zp1&#34;,你必须将它用于每一段代码,包括Qt本身。这样的编译器标志使得用它们编译的代码与不使用它们编译的代码不兼容。

此外,&#34; / Zp1&#34;是一个性能杀手。如果你想打包结构以将它们转储到磁盘等,你就会以错误的方式处理它。您使用的结构不应该打包。只有当您将其复制到磁盘或从磁盘复制时,如果您在内部定义了另一个打包的结构,并且您首先将数据从解压缩复制到打包结构,然后才转储到磁盘。您应该使用适当的编译指示/属性打包单个结构,一切!

答案 2 :(得分:0)

我不得不更改一些Visual Studio构建选项来解决这个问题!

  • 优化=自定义(配置属性 - &gt; C / C ++ - &gt; 优化)
  • 内联函数扩展=默认(配置 属性 - &gt; C / C ++ - &gt;优化)