英文:
Why is my C destructor not getting called?
问题
我有两个项目部分:一个包含主函数的example.c
和一个包含所有API的api.c
。它们分别编译,由API生成的二进制文件被示例用于成功进行API调用。
我已经设置了两个库,包含构造函数和析构函数:
example.c
__attribute__((constructor)) static void example_constructor() {
printf("constructor: example\n");
api_setup();
}
__attribute__((destructor)) static void example_destructor() {
printf("destructor: example\n");
api_teardown();
}
int main() {
// 进行API调用
}
api.c
__attribute__((constructor)) static void api_constructor() {
printf("constructor: api\n");
}
__attribute__((destructor)) static void api_destructor() {
printf("destructor: api\n");
}
api_setup() {
// 为API调用分配一个缓冲区
}
api_teardown() {
// 读取+对缓冲区执行任务。发送到输出文件
// 释放缓冲区
}
// 其他用于操作缓冲区的API定义
当像上面这样设置时,构造函数和析构函数都会在示例和API的主函数开始/结束时调用。事情运行得很顺利,但我希望api.c
的构造函数/析构函数负责所有的设置和拆卸工作。如果我进行以下更改:
api.c
__attribute__((constructor)) static void api_constructor() {
printf("constructor: api\n");
api_setup(); // 在api.c构造函数中执行设置,而不是在example.c构造函数中执行
}
__attribute__((destructor)) static void api_destructor() {
printf("destructor: api\n");
api_teardown(); // 在api.c析构函数中执行拆卸,而不是在example.c析构函数中执行
}
// 其他用于操作缓冲区的API定义(包括设置/拆卸)
将设置移至api.c
构造函数后,我发现构造函数会为example.c
和api.c
都调用,但析构函数只会为example.c
调用。
这是为什么呢?我该如何通过api.c
的构造函数/析构函数执行所有的设置/拆卸工作?
这是你要翻译的部分。
英文:
I have two parts of my project: an example.c
(which contains our main function) and an api.c
(which contains all APIs). They are compiled separately, and the binaries generated by the API are used by the example to successfully make API calls.
I have set up both libraries to contain a constructor and destructor:
example.c
__attribute__((constructor)) static void example_constructor() {
printf("constructor: example\n");
api_setup();
}
__attribute__((destructor)) static void example_destructor() {
printf("destructor: example\n");
api_teardown();
}
int main() {
// make API calls
}
api.c
__attribute__((constructor)) static void api_constructor() {
printf("constructor: api\n");
}
__attribute__((destructor)) static void api_destructor() {
printf("destructor: api\n");
}
api_setup() {
// malloc a buffer to be used in the API calls
}
api_teardown() {
// read + perform task on buffer. send to output file
// free buffer
}
// other API definitions to manipulate the buffer
When set up like the above, constructors and destructors get called for both the example and API (at the start/end of example's main). Things work great but I'd like to have the api.c
constructor/destructor responsible for all setup and teardown work. If I make changes:
api.c
__attribute__((constructor)) static void api_constructor() {
printf("constructor: api\n");
api_setup(); // doing setup in api.c constructor instead of example.c constructor
}
__attribute__((destructor)) static void api_destructor() {
printf("destructor: api\n");
api_teardown(); // doing teardown in api.c destructor instead of example.c destructor
}
// other API definitions to manipulate the buffer (including setup/teardown)
With the setup moved to the api.c
constructor, I find that constructors get called for both example.c
and api.c
, but the destructor only gets called for example.c
.
Why is this? And how could I go about performing all setup/teardown via the api.c
constructor/destructor?
答案1
得分: 3
- 使用这个属性在gcc中,你可以控制构造函数/析构函数的优先级。
- 对于
constructor
,较小的数字表示较高的优先级。 - 对于
destructor
,较小的数字表示较低的优先级。
void __attribute__((constructor(101))) c1(void) { printf("%s\n", __func__);}
void __attribute__((constructor(102))) c2(void) { printf("%s\n", __func__);}
void __attribute__((constructor(103))) c3(void) { printf("%s\n", __func__);}
void __attribute__((constructor(104))) c4(void) { printf("%s\n", __func__);}
void __attribute__((destructor(101))) d1(void) { printf("%s\n", __func__);}
void __attribute__((destructor(102))) d2(void) { printf("%s\n", __func__);}
void __attribute__((destructor(103))) d3(void) { printf("%s\n", __func__);}
void __attribute__((destructor(104))) d4(void) { printf("%s\n", __func__);}
void main(void)
{
}
链接:https://godbolt.org/z/9aGnnW487
英文:
Using this attribute in gcc you can control the priority of the constructors/destructors.
- for
constructor
smaller number means a higher priority - for
destructor
smaller number means a lower priority
void __attribute__((constructor(101))) c1(void) { printf("%s\n", __func__);}
void __attribute__((constructor(102))) c2(void) { printf("%s\n", __func__);}
void __attribute__((constructor(103))) c3(void) { printf("%s\n", __func__);}
void __attribute__((constructor(104))) c4(void) { printf("%s\n", __func__);}
void __attribute__((destructor(101))) d1(void) { printf("%s\n", __func__);}
void __attribute__((destructor(102))) d2(void) { printf("%s\n", __func__);}
void __attribute__((destructor(103))) d3(void) { printf("%s\n", __func__);}
void __attribute__((destructor(104))) d4(void) { printf("%s\n", __func__);}
void main(void)
{
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论