Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.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 - Fatal编程技术网

C 我应该相信调用库初始值设定项函数是为了提高性能吗?

C 我应该相信调用库初始值设定项函数是为了提高性能吗?,c,C,我正在用C(而不是C++)创建一个库,并且有一个关于什么是常见做法的问题 此库需要调用一个%libname%\u Init()函数,以便其他函数可以执行其相应的职责(否则,将发生未定义/意外的行为,可能导致崩溃) 如果用一个简单的if(%random\u var%)调用它,我可以很容易地在每个函数的顶部进行检查,所以我想知道在这方面是否有约定 Psü:一个真实的例子是SDL.h要求SDL_Init(/*模块要初始化*/) Ps²:如果stackoverflow不是解决此类问题的地方,我深表歉意如

我正在用C(而不是C++)创建一个库,并且有一个关于什么是常见做法的问题

此库需要调用一个
%libname%\u Init()
函数,以便其他函数可以执行其相应的职责(否则,将发生未定义/意外的行为,可能导致崩溃)

如果用一个简单的
if(%random\u var%)
调用它,我可以很容易地在每个函数的顶部进行检查,所以我想知道在这方面是否有约定

Psü:一个真实的例子是
SDL.h
要求
SDL_Init(/*模块要初始化*/)


Ps²:如果
stackoverflow
不是解决此类问题的地方,我深表歉意

如果您不介意利用gcc(以及其他可能的)扩展,您可以看看
\uu属性(构造函数))
(请参阅),它保证在
main()
之前立即调用函数。这样您就知道您的init函数已被调用

然而,在一般情况下,如果您的库需要初始化,那么它可能是做错了。您可能根本不想在库中使用globals,这意味着您不想使用这种init函数

作为落入此陷阱的大型库的示例,请看
libxml2
。它有一个init函数,您需要调用它来分配内存。为了让任何人看到(例如,
valgrind
的干净输出,他们需要释放分配的内存,因此他们必须调用deinit函数;当然,只有一些应用程序可以做到这一点。到现在为止,一直都还不错。但如果另一个库(libfoo)也使用
libxml2
,会发生什么呢?它们都调用init函数(很棒)。但如果有人调用Denit函数,又会是谁呢?如果libfoo不调用它,那么任何使用libfoo的东西都会泄漏内存。如果libfoo确实调用了它,那么任何使用libfoo的东西在使用libfoo之后都不能使用libxml2。一团糟(作者承认)

更好的策略是每个用户获取库的上下文(通过一个调用,返回一个指针),它分配一个
struct
,其中包含您本来可以用作全局变量的内容。此指针将传递给每个调用。这样您就知道必须调用了init函数,因为这是获取此类指针的唯一方法。此外,如果每个上下文仅由一个线程使用,那么您的库几乎是自动线程安全的(显然,您需要避免使用任何本身依赖于全局变量的函数)。例如:

 BarContext context = bar_newcontext();
 ...
 bar_dosomething (context, ...);
 ...
 bar_freecontext (context);

我认为这取决于您是否负担得起检查每个函数调用的开销,但取决于您需要多少性能,我认为这不会是一个巨大的开销。但是,您可以使用包含函数执行所需的所有数据的结构,强制调用方对其进行初始化,并将其传递给每个函数,我已经见过很多这种技术,例如查看
cairo
绘图库。您可以使用
assert()
,如果库未初始化,则会失败。这样,发布性能不会受到影响,调试版本显然会捕获错误。现在,不管你们是否应该这样做,这个问题可能更适合程序员。stackexchange.com。谢谢你们的回答,伙计们,我真的很感激你们所有的回答都非常有用。谢谢你的帮助。我现在将实现这个结构上下文。