2012-12-16 159 views
2

最近,我一直在嘗試做一個小測試程序來與C++中的MySQL服務器進行通信。我目前使用MySQL Connector/C++作爲我的API連接到我的數據庫服務器。我花了很長時間纔得到它,因爲oracle/mysql幾乎沒有關於如何在Visual Studio 10+中使用connector/C++的文檔。/gs選項導致程序拋出異常

最終在所有工作都完成後,應用程序嘗試退出時似乎出現了一些問題。它拋出以下未處理的異常:

Unhandled exception at 0x00C62291 in mysql2.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.

研究有關該錯誤後,我想通了,這是由於「安全檢查」選項(/ GS編譯器選項)。當我禁用此編譯器選項時,應用程序將正常退出。

我有一種感覺,我不應該關閉它,因爲它是在Visual Studio 2012的默認選項

我的問題是(可能還有其他版本?):

  • 這是爲什麼/ gs編譯器選項導致未處理的異常?
  • 關閉/ gs編譯器選項安全嗎?

下面是一段代碼未處理的異常點(一個文件中,名爲:gs_report.c):

#if defined (_M_IX86) || defined (_M_X64) 
    if (IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE)) 
#endif /* defined (_M_IX86) || defined (_M_X64) */ 
    __fastfail(FAST_FAIL_STACK_COOKIE_CHECK_FAILURE); 

這裏是我的應用程序代碼:

/* Standard C++ includes */ 
#include <stdlib.h> 
#include <iostream> 

/* 
Include directly the different 
headers from cppconn/ and mysql_driver.h + mysql_util.h 
(and mysql_connection.h). This will reduce your build time! 
*/ 
#include "mysql_connection.h" 
#include "mysql_driver.h" 

#include <cppconn/driver.h> 
#include <cppconn/exception.h> 
#include <cppconn/resultset.h> 
#include <cppconn/statement.h> 
#include <cppconn/prepared_statement.h> 

using namespace std; 

int main(void) 
{ 
    cout << endl; 
    cout << "Let's have MySQL count from 10 to 1..." << endl; 

    try { 
     sql::Driver *driver; 
     sql::Connection *con; 
     sql::Statement *stmt; 
     sql::ResultSet *res; 
     sql::PreparedStatement *pstmt; 

     /* Create a connection */ 
     driver = sql::mysql::get_driver_instance(); 
     con = driver->connect("tcp://127.0.0.1:3306", "root", "MSxa5y"); 
     /* Connect to the MySQL test database */ 
     con->setSchema("test"); 

     stmt = con->createStatement(); 
     stmt->execute("DROP TABLE IF EXISTS test"); 
     stmt->execute("CREATE TABLE test(id INT)"); 
     delete stmt; 

     /* '?' is the supported placeholder syntax */ 
     pstmt = con->prepareStatement("INSERT INTO test(id) VALUES (?)"); 
     for (int i = 1; i <= 10; i++) { 
      pstmt->setInt(1, i); 
      pstmt->executeUpdate(); 
     } 
     delete pstmt; 

     /* Select in ascending order */ 
     pstmt = con->prepareStatement("SELECT id FROM test ORDER BY id ASC"); 
     res = pstmt->executeQuery(); 

     /* Fetch in reverse = descending order! */ 
     res->afterLast(); 
     while (res->previous()) 
      cout << "\t... MySQL counts: " << res->getInt("id") << endl; 
     delete res; 

     delete pstmt; 
     delete con; 

    } catch (sql::SQLException &e) { 
     cout << "# ERR: SQLException in " << __FILE__; 
     cout << "() on line " << __LINE__ << endl; 
     cout << "# ERR: " << e.what(); 
     cout << " (MySQL error code: " << e.getErrorCode(); 
     cout << ", SQLState: " << e.getSQLState() << ")" << endl; 
    } 

    cout << endl; 

    return EXIT_SUCCESS; 
} 

回答

3

的/ gs選項允許運行時檢測程序中的錯誤。刪除該選項允許程序退出而不檢測它,但錯誤仍然存​​在。在代碼或庫的某處,堆棧中的內存正在被覆蓋。我會嘗試在代碼上進行二進制搜索,以查看哪條語句導致錯誤。您可能還需要始終檢查所有數據庫調用的返回值。

你絕對不應該禁用此選項。這樣做會隱藏真正的錯誤,並可能讓您的程序面臨黑客攻擊。

+0

我甚至嘗試縮短代碼只是一個簡單的數據庫連接,然後斷開連接。它仍然會給出同樣的錯誤。所以我假設這是由連接器/ C++庫引起的。 – TheAJ

+0

如果您在調試器中逐步瀏覽,您是否可以看到哪些調用正在觸發緩衝區溢出? –