1. 程式人生 > >close掉一個失效的MySQL連線導致的程式崩潰

close掉一個失效的MySQL連線導致的程式崩潰

這在沒有連結池控制的應用中十分常見,而我正好在做和MySQL相關的開發工作,在一般的工具類應用中,並沒有使用連結池進行連線的管理,而是直接使用MySQL提供的C API進行操作。而這給我的程式帶來過很多麻煩

比如程式碼如下


int main() {
  MYSQL *conn = NULL;
  conn = mysql_init(0);
  MYSQL_RES *res;
  if (mysql_real_connect(conn, "10.211.55.32", "ashe", "ashe", "ashe", 13307, NULL, 0) ==
      NULL) {
    cout << "connection error " << mysql_errno(conn) << mysql_error(conn) << endl;
  }

  cout << mysql_ping(conn) << endl;
  mysql_close(conn);
  mysql_close(conn);
  ...
}

當執行到第二個mysql_close(conn)時,程式就會報錯

test_conn(4768,0x7fffb7fff380) malloc: *** error for object 0x7fab7e000000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

即便是存在連結池,假設是我開發的連結池類,類封裝的不夠好,把連線控制代碼直接暴露給了使用者,使用者在使用完連線之後,歸還連結池之前,把這個連線,手動進行了釋放,那連結池在銷燬這個連結時,如果沒有做檢查,直接close掉,也會出現如上相同的問題

所以,最好的辦法就是,在任何關閉連線的操作前,進行連線存活狀態檢測。程式碼可以修改為

int main() {
  MYSQL *conn = NULL;
  conn = mysql_init(0);
  MYSQL_RES *res;
  if (mysql_real_connect(conn, "10.211.55.32", "ashe", "ashe", "ashe", 13307, NULL, 0) ==
      NULL) {
    cout << "connection error " << mysql_errno(conn) << mysql_error(conn) << endl;
  }

  cout << mysql_ping(conn) << endl;
  mysql_close(conn);
  if(mysql_ping(conn) ==0 )//連線存活
  {
    mysql_close(conn);
  }
  ...
}