簡體   English   中英

發生緩沖區溢出

[英]A buffer overrun has occurred

幾天前,出於安全性考慮,我公司將操作系統從Windows XP更改為Windows 7(32位)。

我在VS 2008,QT 4.8.1和Boost中使用C ++。 我的應用程序中的結構成員對齊是1個字節(/ Zp1)。

更改后,我發現了一個錯誤:

我打開我做出的庫QPluginLoader ,然后我用qobject_cast丟給我的接口。 在我的庫中,我可能會加載另一個。

更改操作系統后,當我在調試模式下測試我的應用程序時,一切正常。 一切都按預期進行,然后將其更改為Release,我的應用程序開始崩潰。

當我用VS 2008調試它時,我看到了此錯誤:

my_app.exe中發生緩沖區溢出,它損壞了程序的內部狀態。 按Break調試程序,或按Continue終止程序。

有關更多詳細信息,請參見幫助主題“如何調試緩沖區溢出問題”。

該應用程序在Windows XP(發行和調試模式)上仍然可以正常運行。

一開始,我以為是因為依賴或我錯過了某些東西。 經過幾個小時的測試,並以發布模式登錄來跟蹤我的應用程序,我終於找到了問題所在。 當一種方法試圖將值(任何值)返回給在庫中調用它的另一個方法時,我的應用程序崩潰。

例如:

方法B返回Bool,我在方法A中調用它。當方法B完成並准備將Bool值返回給方法A時,應用程序崩潰。 如果要返回加載庫的方法(如果該方法返回值),也會崩潰。 不知何故,可以使用不返回任何值(無效)的方法。

為了確定到底出了什么問題,我在方法中的代碼創建了另一個應用程序(測試器),並開始逐部分添加代碼以查找錯誤。 我相信這與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()並運行該應用程序以確保確定。

怎么了 我想念什么?

這段代碼:

PluginInterface* plugin_instance;

if (plugin) 
{

    SecureZeroMemory(&plugin_instance, sizeof(PluginInterface));

    plugin_instance = qobject_cast<PluginInterface *>(plugin);

}

如果SecureZeroMemory做到了它的名字所說的那樣,將會導致很多崩潰。

要使指針歸零,只需將其設置為0。

但是,還要提及的是,如上所述,當您要做的另一件事是將其分配給它時,這將毫無意義

我已經在沒有SecureZeroMemory的情況下進行了測試,但是它仍然崩潰,SecureZeroMemery並不是崩潰的原因!

在代碼的其他地方可能還存在其他類似的錯誤-您未顯示的地方。

至少,您是否使用相同的編譯器並使用相同的設置來編譯應用程序中的所有內容 (所有庫,DLL等)? 如果使用“ / Zp1”,則必須對每段代碼都使用它,包括Qt本身。 這種編譯器標志使使用它們編譯的代碼與不使用它們編譯的代碼不兼容。

此外,“ / Zp1”是性能殺手。 如果要打包結構以將其轉儲到磁盤等中,那將是錯誤的方法。 您使用的結構不應打包。 僅當您將其復制到磁盤或從磁盤復制時,才應在內部定義另一個打包的結構,然后首先將數據從解壓縮復制到打包的結構,然后再轉儲到磁盤。 您應該使用適當的編譯指示/屬性而不是所有內容來打包單個結構!

我不得不更改一些Visual Studio生成選項來解決此問題!

  • 優化=自定義(配置屬性-> C / C ++->優化)
  • 內聯函數擴展=默認(配置屬性-> C / C ++->優化)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM