gpt4 book ai didi

c - 在 C 中退出之前使用全局指针数组进行清理

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:54:49 25 4
gpt4 key购买 nike

我有一个小程序,其中包含一个我需要 malloc 的变量:

char **v;
v = (char**)malloc(sizeof(char *) * MAX_EVENTS);
for (int i = 0; i < MAX_EVENTS; i++)
v[i] = (char *)malloc(MAX_NAME_SIZE);

为了让 Valgrind 满意,避免任何内存泄漏,我为终止信号设置了处理程序。此处理程序将在退出之前简单地释放该分配,并终止子进程。

 static void term_handler() {
if (v != NULL) {
for (int i = 0; i < MAX_EVENTS; i++) {
if (v[i] != NULL)
free(v[i]);
}
free(v);
}
for (int i = 0; i < MAX_PROCS; i++)
if (children[i])
kill(children[i], SIGTERM);
exit(EXIT_SUCCESS);
}

为了从处理程序访问 v,我将它作为一个全局变量。 children 是一个静态数组 pid_t children[MAX_PROCS]; 但也可能是 malloced

从处理程序访问这些分配的最干净的方法是什么?不推荐使用全局变量,但内存泄漏和未正确终止的程序也不推荐。我应该保留一个指向我的分配的指针数组作为全局变量吗?还是我应该避免处理意外信号?

最佳答案

信号处理程序很棘手,因为它们是异步调用的,因此只有一个 small set of function calls。从信号处理程序中调用是安全的。特别是,在信号处理程序中分配或释放内存是禁忌(调用 exit() 也是如此!),所以不要这样做。

但是,如果您想确保内存得到释放 (*),您可以通过让信号处理程序“告诉”程序的主线程它退出的时间到了。然后,主线程可以跳出它的事件循环,释放内存,并执行它通常在退出前执行的任何其他清理工作。

那么问题就变成了,信号处理程序如何安全地告诉主线程执行受控/正常退出?

如果主线程正在运行一个按固定计划执行的事件循环(例如每隔这么多毫秒),它可能就像声明一个全局变量一样简单(例如 volatile bool pleaseQuitNow = false; 主线程在其事件循环的每次迭代中进行测试,并让信号处理程序将该变量设置为不同的值。然后主线程将在其下一次迭代中看到已更改的变量,并通过中断事件进行响应循环。

另一方面,如果主线程的事件循环是基于事件的(例如,它在 select()poll() 或类似的内部被阻塞并且调用不会在不确定的时间内返回),则另一种唤醒主线程的方法是创建一个 pipe()socketpair()在程序启动时,让主线程监视两个文件描述符之一的读取就绪状态。然后当信号处理程序运行时,它可以 send() 另一个文件描述符上的一个字节,这将导致第一个文件描述符指示准备好读取状态。主线程可以通过中断其事件循环并优雅地退出来响应该准备就绪状态。

除了避免异步信号不安全调用之外,这样做的好处是您只有一个关闭/清理路径来测试/调试/维护,而不是两个。

(*) 当然,在任何现代操作系统上,内存都会被操作系统的进程清理例程释放;但是 valgrind 会提示内存泄漏,所以如果可能的话,最好手动释放内存,如果只是这样你就可以使用 valgrind 找到“真正的”内存泄漏,而不必每次都对一堆误报进行分类。

关于c - 在 C 中退出之前使用全局指针数组进行清理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54057582/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com