【问题标题】:Duplicate Symbol when including header only library more than once多次包含仅标头库时重复符号
【发布时间】:2017-12-29 10:02:49
【问题描述】:

我为我正在制作的一个小游戏制作了一个简单的助手库。在这样的库中,我有一些核心函数必须尽可能快地执行,因为它们在每个游戏帧中被调用数千次。

如果我将它们声明为“内联”并将它们的声明 (library.h) 从它们的实现 (library.c) 中分离出来并将它们包含在游戏文件 (game.c) 中,我猜它们没有被内联/优化,因为直接在game.c 中声明它们并使用gcc -O3 编译游戏给了我60 倍以上的性能提升。

为了解决这个问题,我决定让我的库成为一个只有头文件的库。我在library.h 中有我所有的框架常量、变量和函数。将它包含在 game.c 中仍然可以为我提供最佳性能。

现在,问题是每当我在多个文件中包含library.h(比如game1.cgame2.c)时,我都会在编译游戏时得到一长串duplicate symbol 错误。该库有#pragma once,但问题仍然存在。

如何实际编写仅包含头文件的库或确保外部库中的内联函数实际得到优化?

谢谢

【问题讨论】:

  • 您是否在头文件中定义变量或函数?
  • 您只想在标头中声明变量并有一个单独的.c 文件用于定义
  • 你要声明函数static

标签: c


【解决方案1】:

正如alk已经评论的那样,您需要在头文件static中声明函数和全局变量。

static 关键字表示对象(函数或变量)具有内部链接;它只在当前编译单元中可见,不会包含在任何符号表中。

使用包含保护也是一个好主意,这样如果您有另一个包含您的头文件的头文件,并且 C 源文件同时包含您的头文件和其他头文件,您的头文件只会被包含一次. (带有FOOLIB_H 的行构成了以下示例中的包含保护。)

考虑以下简单的固定大小堆栈示例,foolib.h

#ifndef   FOOLIB_H
#define   FOOLIB_H

#include <stdlib.h>

#define   STACK_MAX  256

static size_t  stack_size = 0;
static double  stack_item[STACK_MAX];

static inline int  stack_push(const double  item)
{
    if (stack_size < STACK_MAX) {
        stack_item[stack_size++] = item;
        return 0;
    } else
        return -1;
}

static inline double  stack_pop(const double  empty)
{
    if (stack_size > 0)
        return stack_item[--stack_size];
    else
        return empty;
}

#endif /* FOOLIB_H */

包含上述 (#include "foolib.h") 的每个编译单元(您单独编译的每个源文件)都有自己的本地私有堆栈,可以通过 stack_push()stack_pop() 使用。

标记函数static inline 而不仅仅是static 的原因是前者告诉编译器可以完全省略该函数,如果不使用它。特别是,如果你用gcc -Wall 编译代码,如果static 函数未被使用,gcc 会发出警告,但如果static inline 函数未被使用则不会发出警告。除此之外,没有太大的实际区别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 2020-09-23
    • 2012-11-07
    • 1970-01-01
    • 2014-07-09
    • 1970-01-01
    相关资源
    最近更新 更多