首页 > 解决方案 > 使对象只能由其库访问,而不能由程序中的任何其他例程访问

问题描述

假设我有两个(或更多)c 函数func1(),并且func2()都需要一个缓冲区变量int buff。如果这两个函数都保存在单独的文件func1.cfunc2.c中,我如何制作它以便buff只能访问func1()func2()不是调用例程(或任何其他例程)。
这是一个示例设置:

文件func1.c

/*func1.c*/
static int buff;

int *func1(int x)
{
    buff = x;
    return &buff;
}

文件func2.c

/*func2.c*/
static int buff;

int *func2(int x)
{
    buff = x;
    return &buff;
}

标头header.h

/*header for func1.c and func2.c*/
//multiple inclusion guard not present.
int *func1(int);
int *func2(int);

文件main.c

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

int main()
{
    int *ptr;

    ptr = func1(1);
    printf("&buff = %p , buff = %d\n", ptr, *ptr);
    ptr = func2(2);
    printf("&buff = %p , buff = %d\n", ptr, *ptr);

    return 0;
}

正如预期的那样,输出显示了 buff 的不同内存位置。

&buff = 0x55b8fd3f0034 , buff = 1
&buff = 0x55b8fd3f0038 , buff = 2

但我只需要一个副本buff,不需要更多。
当然,我可以将两个函数放在同一个文件中,并定义buffstatic int但是我将失去分别编译函数的能力。
如果我放入int buff一个单独的buff.c并在func1.cfunc2.c 中将其声明为extern,那么调用例程(在本例中为 main )将很容易访问它。


基本上,我需要创建一个在同一个外部对象上工作的函数库,只有它们可以访问。调用例程可能不需要所有函数,因此我不想将它们放在一个文件中并创建未使用的代码。但是对象必须只有一个副本。

如果可以的话,请帮助我如何做同样的事情。

标签: c++cobject

解决方案


C 标准没有提供执行此操作的方法。它通常使用 C 标准之外的编译器和链接器的特性来完成。这是在 macOS 上使用 Apple 开发人员工具的示例。对于适合您环境的选项,您应该指定您正在使用的构建工具和版本,例如您使用的是 Apple 工具、GNU 工具、Microsoft 工具还是其他工具。

有了这个a.c

#include <stdio.h>

int x = 123;

void a(void)
{
    printf("In a.c, x is %d.\n", x);
}

这在b.c

#include <stdio.h>

extern int x;

void b(void)
{
    printf("In b.c, x is %d.\n", x);
}

我们将源文件编译为目标模块:

clang -c a.c b.c

然后将它们链接到新的目标模块,同时请求不导出r.o符号x(在链接器视图中):_x

ld -r -o r.o -unexported_symbol _x a.o b.o

然后,如果我们有另一个源文件c.c尝试使用x

#include <stdio.h>

extern int x;

extern void a(void);
extern void b(void);

int main(void)
{
    a();
    b();
    printf("In c.c, x is %d.\n", x);
}

尝试使用clang -o c c.c r.o yield 构建可执行文件:

架构 x86_64 的未定义符号:
  “_x”,引用自:
      _main 在 c-139a35.o
ld:未找到架构 x86_64 的符号

c.c但是,如果我们删除引用的两行x,则构建成功,程序将打印:

在 ac 中,x 是 123。
在公元前,x 是 123。

推荐阅读