2012-07-12 91 views
3

我正在使用MySQL 5.0.51a我發現了一個錯誤,當我的程序退出時,導致無限循環(以堆棧溢出和seqgfault結尾)。意外的函數調用

我發現如果我有一個叫shutdown()的函數,它會在調用mysql_close()期間被調用。

我已經在下面包含了一個簡單的C源代碼文件和makefile文件來展示這個問題。 在該示例中,shutdown()被調用,儘管未被main()調用。

這是怎麼回事?我的shutdown()與libmysqlclient中的shutdown()相沖突嗎? 如果是這樣,gcc不知道它有什麼原因嗎?

我用gcc(GCC)4.2.4(Ubuntu的4.2.4-1ubuntu4)


mysql_shutdown.c:

#include <stdio.h> 
#include <mysql/mysql.h> 

#define HOST "<hostname>" 
#define USER "<username>" 
#define PASSWD "<password>" 
#define DB "<dbname>" 

MYSQL *connection; 

void shutdown(void) 
{ 
    printf("shutdown called\n"); 
} 

int main() 
{ 
    connection = mysql_init(NULL); 
    mysql_real_connect(connection, HOST, USER, PASSWD, DB, 0, NULL, 0); 
    mysql_close(connection); 

    return 0; 
} 

生成文件:

mysql_shutdown: mysql_shutdown.c 
     gcc -Wall -Wextra -Werror `mysql_config --cflags` -o [email protected] $^ `mysql_config --libs` 

輸出:

$ ./mysql_shutdown 
shutdown called 

請注意,這似乎與GCC function name conflict中顯示的行爲相反。在這種情況下,預期的函數沒有被調用,而在我的情況下,函數在不被期望時被調用。

+4

也許你應該嘗試'gcc -Wall'? – Bobby 2012-07-12 13:25:44

+1

你正在包含mysql的頭文件。編譯器只是因爲它很弱而且你的強大而忽略了其他定義。 (我認爲) – 2012-07-12 13:33:04

+0

@Bobby我實際上一直在使用「-Wall -Wextra -Werror」。我錯誤地沒有在帖子中包括他們。我現在編輯它。無論如何,它們對行爲沒有影響。 – 2012-07-12 14:09:23

回答

1

什麼是最有可能發生的是,因爲mysql_config --libs是給你的MySQL庫文件的列表和shutdown()功能是在圖書館(S)內的不同目標文件,它沒有被在買。

你必須瞭解大多數連接器的工作方式。他們要做的就是將所有你明確列出的目標文件捆綁在一起,最終得到部分可執行文件和尚未解決的符號列表。

然後,通過在可以解析符號的那些庫中查找對象文件來努力解決這些符號的搜索。通常會發生的情況是,您會在其中一個庫中找到mysql_close(),並從該庫中加載其目標文件。但是這種行爲可能會引入更多需要解析的符號,這可能會導致搜索更多的庫。

作爲一個例子,假設mysql_close()調用shutdown(),它通常在其中一個MySQL庫中提供。但是,由於您已經已經定義了,所以mysql_close()的加載確實是而不是導致具有未解決的shutdown符號。所以沒有必要去任何圖書館去尋找它。

確實結果mysql_close()調用一個完全不同的shutdown(),你在你的代碼中提供的一個。