【问题标题】:undefined reference to pthread_create and pthread_join对 pthread_create 和 pthread_join 的未定义引用
【发布时间】:2017-10-15 00:04:31
【问题描述】:

我正在尝试构建我的程序,但不断收到相同的错误消息:

undefined reference to pthread_create  
undefined reference to pthread_join

我已包含 pthread.h 并在我的 makefile 中使用 -pthread 编译。

int threadAmount = strtol(nrthr, NULL, 0);
    threadAmount--;

    if(threadAmount > 0){
        pthread_t tids[threadAmount];

        for(int i = 0;i < threadAmount; i++){
            pthread_attr_t attr;
            pthread_attr_init(&attr);
            pthread_create(&tids[i],&attr,search,&t1);
        }

        for(int i = 0;i < threadAmount; i++){
            pthread_join(tids[i],NULL);
        }
    }

这就是我在抱怨的地方创建和加入的地方。可能是什么问题?

用于构建的makefile:

CC=gcc
CFLAGS= -pthread -std=gnu11 -Wall -Wextra -Werror -Wmissing-declarations -Wmissing-prototypes -Werror-implicit-function-declaration -Wreturn-type -Wparentheses -Wunused -Wold-style-definition -Wundef -Wshadow -Wstrict-prototypes -Wswitch-default -Wunreachable-code

all: mfind

list.o: list.c list.h
    $(CC) -c list.c $(CFLAGS)

mfind.o: mfind.c list.h
    $(CC) -c mfind.c $(CFLAGS) 

mfind: mfind.o list.o
    $(CC) mfind.o list.o -o mfind

clean:
    rm -f *.o mfind

mfind 是主程序,list.c 是一个实现的列表。

【问题讨论】:

  • 您的建设情况如何?编辑您的问题并添加该信息。这是一个链接器错误,pthread 库没有以某种方式链接
  • 我在makefile中添加了,够了吗? @yano
  • 链接时的顺序很重要。尝试从CFLAGS 中删除-pthread 并执行$(CC) mfind.o list.o -pthread -o mfind。通常有编译器标志(您的 CFLAGS)和链接器标志(-pthread 将进入链接器标志变量,编译器不应该需要它)。但是,我不是 makefile 专家。
  • 甜蜜!一般来说,如果codeA.o 调用codeB.o 中的函数,那么您必须在链接器命令中与codeA.o before codeB.o 链接.. 反正这是我的经验。
  • -pthread 会影响预处理器宏和链接,因此最好始终将其指定给“gcc”驱动程序。

标签: c linux multithreading linker-errors


【解决方案1】:
list.o: list.c list.h
    $(CC) -c list.c $(CFLAGS)

mfind.o: mfind.c list.h
    $(CC) -c mfind.c $(CFLAGS) 

mfind: mfind.o list.o
    $(CC) mfind.o list.o -o mfind

您的某些食谱似乎缺少CFLAGS,其中包括选项-pthread。我认为应该是:

list.o: list.c list.h
    $(CC) $(CFLAGS) -c list.c

mfind.o: mfind.c list.h
    $(CC) $(CFLAGS) -c mfind.c

mfind: mfind.o list.o
    $(CC) $(CFLAGS) mfind.o list.o -o mfind

...

CFLAGS 可以输出工件。实际上,当编译器驱动程序驱动链接时,您应该使用相同的CFLAGS(和CXXFLAGS)。您还应该始终使用编译器驱动程序,因为它负责将 -pthread-fopenmp-fsanitize=undefined 等选项转换为链接器的正确选项和库。

如果有兴趣,以下是 GNUmake 使用的默认规则:Catalogue of Built-In Rules。注意*.c 文件的配方包括CFLAGS

编译 C 程序

n.on.c 自动生成,配方形式为 $(CC) $(CPPFLAGS) $(CFLAGS) -c

如果您使用 GNU Make 手册中的以下内容,那么您还应该将 -pthread 添加到 LDFLAGS。但是我建议你按照编译器的人告诉我们的,那就是通过编译器驱动来驱动链接。

链接单个对象文件

n 通过运行链接器从n.o 自动生成(通常 通过 C 编译器调用 ld)。使用的精确配方是$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)

【讨论】:

    【解决方案2】:

    -pthread 不属于CFLAGS。正如您已经发现的那样,所需的库必须位于所有目标文件之后的命令行选项的末尾。您需要将-pthread 放入LDLIBS,因为您有一个makefile。

    来自https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html

    LDLIBS

    当编译器应该调用链接器“ld”时为编译器提供的库标志或名称。 LOADLIBES 是 LDLIBS 的已弃用(但仍受支持)替代方案。非库链接器标志,例如 -L,应该放在 LDFLAGS 变量中。

    【讨论】:

    • 据我了解,-pthread 属于CFLAGSCXXFLAGS。编译器驱动程序会看到它,并根据需要添加-D_REENTRANT(和其他选项)。当编译器驱动程序链接时,它还将使用适当的标志和库调用链接器。
    • “编译器驱动程序将看到它,并根据需要添加 -D_REENTRANT(和其他选项)。当编译器驱动程序链接时,它还将使用适当的标志和库调用链接器” - 可能有对于古代 C 库来说是这样,以便生成线程代码,但现在不再如此。在CFLAGSLDLIBS 中都有-pthread 并没有什么坏处,但不需要在CFLAGS 中拥有它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 2013-06-20
    • 1970-01-01
    • 2016-03-12
    相关资源
    最近更新 更多