Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何合并头定义的内联函数的所有实例的静态?_C_Linux_Gcc_Clang_Elf - Fatal编程技术网

C 如何合并头定义的内联函数的所有实例的静态?

C 如何合并头定义的内联函数的所有实例的静态?,c,linux,gcc,clang,elf,C,Linux,Gcc,Clang,Elf,有一个定义了一些静态内联函数的头,其中包含静态变量,如何在组成最终可加载模块的所有TU中实现相同静态局部变量的合并?。以不那么抽象的方式: /* * inc.h */ #include <stdlib.h> /* * This function must be provided via header. No extra .c source * is allowed for its definition. */ static inline void* getPtr() {

有一个定义了一些
静态内联
函数的头,其中包含
静态
变量,如何在组成最终可加载模块的所有TU中实现相同静态局部变量的合并?。以不那么抽象的方式:

/*
 * inc.h
 */
#include <stdlib.h>

/* 
 * This function must be provided via header. No extra .c source
 * is allowed for its definition.
 */
static inline void* getPtr() {
    static void* p;
    if (!p) {
        p = malloc(16);
    }
    return p;
}

/*
 * 1.c
 */
#include "inc.h"

void* foo1() {
    return getPtr();
}

void* bar1() {
    return getPtr();
}

/*
 * 2.c
 */
#include "inc.h"

void* foo2() {
    return getPtr();
}

void* bar2() {
    return getPtr();
}

很可能两个TU都会收到自己的
getPtr.p
。尽管在每个TU中,
getPtr.p
在所有
getPtr()实例化中共享。这可以通过检查最终可加载二进制文件来确认:

$ readelf -s --wide a.out | grep getPtr
    32: 0000000000201030     8 OBJECT  LOCAL  DEFAULT   21 getPtr.p
    34: 0000000000201038     8 OBJECT  LOCAL  DEFAULT   21 getPtr.p
同时,我正在寻找一种方法,来跨单独的TU边界共享
getPtr.p
。这与C++模板实例化的情况类似。很可能
GRP\u COMDAT
会对我有所帮助,但我找不到任何关于如何标记要放入COMDAT的静态var的信息


是否有任何属性或其他源代码级别(不是编译器选项)的方法来实现合并此类对象?

如果我正确理解您的要求,只需声明一个全局变量即可实现此效果

/*
*公司
*/
无效*我的;
静态内联void*getPtr(){
如果(!我的){
my_p=malloc(16);
}
归还我的护照;
}
这将在整个程序中对
getPtr
的所有实例使用相同的变量
my_p
(因为它是全局变量)。而且在任何模块中都不需要明确定义
my\p
。它将被初始化为
NULL
,这正是您想要的。因此,除了
inc.h
之外,不需要更改任何内容,也不需要额外的
.c
文件

当然,您可能希望给
my_p
一个不太可能与用户程序中的任何标识符冲突的名称。可能是
Sergios\u包含\u getPtr的\u文件\u p\u或类似的东西

这实际上是标准C的扩展(在N2176的附录J.5.11中提到),但它是由gcc和clang在大多数现代平台上提供的。它记录在
-fcomon
编译器选项下(默认情况下启用)。它通常通过将变量放在
common
部分来实现,然后链接器将所有实例合并在一起,就像您建议的那样。但是上面的代码显示了如何访问该功能,而不需要使用属性或其他模糊的咒语


如果你想变得特别偏执,你可以用
\uu属性((公共))
声明
my\u p
,这将导致变量以这种方式处理,即使
-fno-common
有效。(当然,如果由于某种原因而使用了
-fno common
),则可能会导致问题…

所有TU中相同的静态局部变量
-So。。难道你不能通过提供一个变量的单一定义,将定义移动到文件范围并合并所有TU中的变量吗?为什么你要求在每个文件中都有一个getPtr代码和静态变量的实例,而在每个文件中,你#包括头后,要求所有文件都只有一个实例?因为你想让函数内联?@KamilCuk是的,这显然是正确的方法。我只是忘了强调我的函数必须在标题中。你可以把它看作是一个“只有标题的图书馆”。布鲁诺因为我不够清楚而责骂我。正如我在上面的评论中所说,定义必须放在标题中。您不能共享静态变量,但可以共享分配的内存,而不是在每个内存中调用malloc,而是使用任何方式来获得相同的分配缓冲区。静态变量不使用大量内存,这与缓冲区不同,缓冲区可能很大!我完全忘记了这些“未分配的外部程序”。是的,这对我来说很有效,不过正如你所说的,数据隔离有所损失。编译器似乎甚至没有把它放到某个部分,而是将这个对象标记为
SHN_COMMON
。现在链接器负责为它分配一个槽位。我刚刚发现,不幸的是,若在cpp源代码中包含头文件,那个么它就不会进行得很顺利。它在每个TU中分配对象,因此链接步骤失败。@塞尔吉奥:也许你想问一个单独的问题,关于如何在C++中这样做。我对那种语言知之甚少。
$ readelf -s --wide a.out | grep getPtr
    32: 0000000000201030     8 OBJECT  LOCAL  DEFAULT   21 getPtr.p
    34: 0000000000201038     8 OBJECT  LOCAL  DEFAULT   21 getPtr.p