【问题标题】:"Undefined reference to" error even function is declared and defined“未定义的引用”错误,即使函数被声明和定义
【发布时间】:2012-07-13 18:59:07
【问题描述】:

我有这 2 个 c 文件和一个头文件。所有这些文件都是由Makefile 构建的。

mysql_storage.h

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

#if 1
typedef enum {
        STORAGE_OK = 0,
        STORAGE_NO_SUCH_USER,
        STORAGE_INVALID_PASSWORD,
        STORAGE_ALREADY_EXISTS,
        STORAGE_OTHER_ERROR/* Error that isn't caused by user input, such as 
                               a database that is unreachable. log() will be 
                               used for the exact error message */
} storage_status_t;

typedef enum
{
    MYSQL_PASS_CHECK_ONLY = -1,
    MYSQL_PASS_UNKNOWN = 0,
    MYSQL_PASS_WRONG,
    MYSQL_PASS_OK
} mysql_pass_st;
#endif

static void mysql_storage_init( void );
static void mysql_storage_deinit( void );
static storage_status_t mysql_storage_load(const char *password );
static storage_status_t mysql_storage_check_pass( const char *nick, const char *password );
static storage_status_t mysql_storage_save( int overwrite );
static storage_status_t mysql_storage_remove( const char *nick, const char *password );

mysql_storage.c

#include "mysql_storage.h"

MYSQL *mysql;

static void mysql_storage_init( void ) {
    if (mysql_init(mysql) == NULL)
        fprintf( stderr, "Can not initialize MySQL. Configuration won't be saved.");

    if (!mysql_real_connect(mysql, "localhost", "USERNAME", "PASSWORD", NULL, 3306, NULL, 0))
        fprintf( stderr, "%s\nConfiguration won't be saved.", mysql_error(mysql));

    if (mysql_select_db(mysql, "DATABASENAME"))
        fprintf( stderr, "%s\nConfiguration won't be saved.", mysql_error(mysql));
}
static void mysql_storage_deinit( void ) {
    if(mysql!=NULL) 
        mysql_close(mysql);
}
static storage_status_t mysql_storage_check_pass( const char *nick, const char *password ){    return STORAGE_OTHER_ERROR;}
static storage_status_t mysql_storage_load(const char *password ){    return STORAGE_OTHER_ERROR;}
static storage_status_t mysql_storage_save( int overwrite ){    return STORAGE_OTHER_ERROR;}
static storage_status_t mysql_storage_remove( const char *nick, const char *password ){    return STORAGE_OTHER_ERROR;}

ma​​in.c

#include<stdio.h>
#include "mysql_storage.h"

    int main(){
        // connect mysql
        mysql_storage_init();
        // check a password
        printf("check password: %d\n:", mysql_storage_check_pass("hello", "world"));
        // close mysql
        mysql_storage_deinit();
    }

最后是 Makefile

CFLAGS=-I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -g -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I.
LIBS=-L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -ldl -lglib-2.0 -L.
CC=gcc

all: main
clean:
        rm main  *.o
main: mysql_storage.o main.o 
        $(CC)  main.o mysql_storage.o $(LIBS) -o main
.c.o:
        $(CC) -c $(CFLAGS) $<

当我做的时候,我得到了这个错误。

gcc  main.o mysql_storage.o -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -ldl -lglib-2.0 -L. -o main
main.o: In function `main':
/home/shiplu/projects/mysql_interface/main.c:8: undefined reference to `mysql_storage_init'
/home/shiplu/projects/mysql_interface/main.c:11: undefined reference to `mysql_storage_check_pass'
/home/shiplu/projects/mysql_interface/main.c:15: undefined reference to `mysql_storage_deinit'
collect2: ld returned 1 exit status

如您所见,我正在链接 main.omysql_storage.o。所以它不应该抛出未定义的引用错误。这里有什么问题?

【问题讨论】:

    标签: c makefile compiler-errors


    【解决方案1】:

    您将函数mysql_storage_init 声明为static,这意味着它们具有内部linkage——这意味着它们对其他翻译单元不可见。

    由于您需要从其他目标文件中调用它们,因此您应该通过在声明和定义中省略 static 关键字来声明它们具有外部链接。头文件中的原型可以选择声明它们extern,但这不是必需的,因为默认情况下链接是外部的。

    【讨论】:

    • 啊哈!我不知道。但我认为其他一些项目是如何声明静态成员并被调用的。
    • 如果我创建静态函数并将函数指针放在非静态结构中,我可以从外部调用它吗?结构将被声明为extern
    • 是的,如果您创建static 函数,您可以将函数指针传递给它们,并通过函数指针在任何地方调用它们。但您只能在同一翻译单元内创建函数指针。
    • 小警告 - 在 Windows 上,如果您将函数声明为 static可能将其调用语义从 __far 更改为 __near要从另一个翻译单元调用的函数。除非您明确需要一个函数是该 .obj 文件的本地函数,否则您不需要将其声明为 static
    【解决方案2】:

    你的 mysql_storage.c 函数被定义为static,这意味着它们在文件之外是不可见的。删除static,它应该可以工作。

    【讨论】:

    • 感谢您的快速回复。我还是 C 的菜鸟
    【解决方案3】:

    函数的static 关键字意味着该函数将具有this .obj file only的范围,这可能不是您所期望的。删除函数定义和声明(.h 和 .cpp 文件)的 static 关键字

    【讨论】:

    • 非常感谢。就是这样。不是它编译好。
    【解决方案4】:

    在函数之前使用关键字 static 可确保它们仅在定义它们的编译单元中可见。如果您从函数中删除 static 关键字,您应该没有问题。

    【讨论】:

      【解决方案5】:

      如果您计划在不同的编译单元中使用函数,则不应将它们声明为静态。

      【讨论】:

      • 这是一个不错的提示。但我认为它应该作为评论。
      • 不,这是对问题的直接回答。这就是链接失败的原因。
      • 这是一个小费。请注意在您之前输入的四个答案提供了多少信息。
      猜你喜欢
      • 1970-01-01
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-09
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      相关资源
      最近更新 更多