我提出这个问题是因为我觉得我不理解C/C++库的一些基本概念.

假设我们有一个库,它保存了一些名为lib_c的状态(例如静态全局变量).假设有另一个库lib_b使用lib_c.

现在,我正在编写一个程序A,它需要lib_b和lib_c.A使用的lib_c与lib_b使用的lib_c有什么不同的方式(即获得静态全局变量的单独副本)?

为了更好地说明我的沮丧,请参见下面的代码示例.

这里是"状态库",它只有两个静态全局值:

C.h:

#ifndef C_H
#define C_H
void init_variables(int a, int b);
int get_a();
int get_b();
#endif

C.C.:(用谷歌翻译翻译)

#include "c.h"
static int a_ = 0, b_ = 0;
void init_variables(int a, int b) {
    a_ = a;
    b_ = b;
}
int get_a() { return a_; }
int get_b() { return b_; }

下面是使用状态库的另一个库:

B.h.

#ifndef B_H
#define B_H
void read_b();
#endif

b. c:

#include <stdio.h>
#include "b.h"
#include "c.h"
void read_b() {
    printf("As seen from b. c: %d, %d\n", get_a(), get_b());
}

下面是我的代码,它使用了两个库:

答:

#include <stdio.h>
#include "b.h"
#include "c.h"

void read_a() {
    printf("As seen from 答: %d, %d\n", get_a(), get_b());
}

int main() {
    init_variables(1, 2);
    read_a();
    read_b();
    return 0;
}

read_a()和read_b()读取静态全局值1和2的相同内容!似乎lib_b和我的代码没有得到这些静态全局值的不同副本.

我试过使用普通gcc命令编译和使用CMake构建.看看我写的CMakeLists:

cmake_minimum_required(VERSION 3.22)

project(UnderstandStatefulLibs VERSION 1.0 LANGUAGES C)

# c.c -> lib_c
add_library(lib_c c.c)

# b.c + lib_c -> lib_b
add_library(lib_b b.c)
target_link_libraries(lib_b PRIVATE lib_c)

# a.c + lib_b + lib_c -> executable
add_executable(main a.c)
target_link_libraries(main PRIVATE lib_b lib_c)

欢迎对这一问题作出任何澄清.我想知道是否有可能获得静态全局值的单独副本,如果有,如何获得.

谢谢你!

推荐答案

通常,需要在内部存储某些状态的库被实现,以便有一个"open_library()"调用分配包含该状态的数据 struct 或类的新副本,并返回一个不透明句柄(例如指向该 struct 的void指针).

在对库的所有其他调用中,用户必须提供句柄作为函数的第一个参数.

还应该有一个"close_library(handle)调用,它释放"open_library()"中分配的状态 struct .

用户看不到状态 struct 的内部,只能通过调用库中的函数并传递句柄来操作包含在它中的数据.

正如OldBoy所指出的,库应该避免使用全局/静态变量进行状态存储,因为当库在多个上下文或线程中使用时,这会导致问题.

C++相关问答推荐

如何避免使用相对路径包含在c中

带双指针的2D数组

为什么信号量为空= 0,而不是阻塞?

常数函数指针优化

sizeof结果是否依赖于字符串的声明?

如何在C中只使用一个带双方括号([i][j])访问语法的malloc来分配动态大小的2d数组?

有没有更简单的方法从用户那里获取数据类型来计算结果

为什么在C中进行大量的位移位?

为什么在此程序中必须使用Volatile关键字?

非常大的数组的大小

为什么该函数不将参数值保存到数据 struct 中?

在创建动态泛型数组时,通过realloc对故障进行分段

用C++实现余弦函数

如何用c语言修改shadow文件hash部分(编程)?

从TCP连接启动UDP(C套接字)

如何确保我将使用C标准库函数的函数版本,如&getc";,而不是类似函数的宏版本?

C语言中奇怪的输出打印数组

宏观;S C调深度

在我的函数中实现va_arg的问题

快速准确计算double的小数指数