意外的函数调用

时间:2012-07-12 13:22:31

标签: mysql c gcc

我正在使用 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 $@ $^ `mysql_config --libs`

输出:

$ ./mysql_shutdown
shutdown called

请注意,这似乎与GCC function name conflict中显示的行为相反。在这种情况下,没有调用期望的函数,而在我的情况下,当不期望函数被调用时。

1 个答案:

答案 0 :(得分:1)

最有可能发生的是,因为mysql_config --libs为您提供了一个MySQL库文件列表,shutdown()函数位于库中不同对象文件中(s),它没有被买进。

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

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

作为一个例子,假设mysql_close()调用shutdown(),它通常在一个MySQL库中提供。但是,由于您已经定义了它,因此加载mysql_close() 而不是会导致出现未解析的shutdown符号。因此,没有必要在任何库中寻找它。

导致mysql_close()调用完全不同的shutdown(),即您在代码中提供的{{1}}。