3

我正在使用MySQL 5.0.51a,当我的程序退出时,我发现了一个导致无限循环(以堆栈溢出和 seqgfault 结束)的错误。

我发现如果我有一个名为 的函数shutdown(),它会在调用mysql_close().

我在下面包含了一个最小的示例 C 源文件和 makefile 以显示问题的实际情况。在示例中,shutdown()尽管未被 调用,但仍被调用main()

这里发生了什么?我是否与libmysqlclientshutdown()中的 a 发生冲突?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 $@ $^ `mysql_config --libs`

输出:

$ ./mysql_shutdown
shutdown called

请注意,这似乎与GCC 函数名冲突中显示的行为相反。在那种情况下,预期的函数没有被调用,而在我的例子中,一个函数在不被预期的时候被调用。

4

1 回答 1

1

最有可能发生的是,因为mysql_config --libs它为您提供了 MySQL 库文件的列表,并且该shutdown()函数位于库中的不同目标文件中,所以它没有被购买。

您必须了解大多数链接器的工作方式。他们要做的是将您明确列出的所有目标文件捆绑在一起,最终得到部分可执行文件和尚未解析的符号列表。

然后通过在那些库中定位可以解析符号的目标文件来搜索库以解析这些符号。通常情况下,您会mysql_close()在其中一个库中找到并从该库加载其目标文件。但是该操作可能会引入更多需要解析的符号,这反过来又会导致更多的库被搜索。

例如,假设通常在 MySQL 库之一中提供的mysql_close()调用。shutdown()但是,因为您已经定义了它,所以加载mysql_close()不会导致出现未解析的符号shutdown。所以没有必要去任何图书馆寻找它。

确实会导致mysql_close()调用一个完全不同shutdown()的 ,即您在代码中提供的那个。

于 2013-08-13T08:41:25.757 回答