【发布时间】:2014-03-07 21:54:43
【问题描述】:
我的代码必须使用 C99 之前的编译器进行编译(我们正在努力更新,但这是一项艰巨的任务),它正在调用以 C99 为设计理念的实用程序库。特别是,这些实用程序定义了一个 hashmap 类型并提供了一个宏来遍历它,类似于以下内容:
#define MAP_FOREACH(key, val, map) \
for (struct _map_iterator iter __attribute__((cleanup(_map_iter_cleanup))); \
(key) = iter->pair->key, \
(value) = iter->pair->value; \
iter = iter->get_next_cb())
实际代码有更多内容(确保迭代器名称唯一的功能等),但这涵盖了我的问题的实质,即 1999 年以前的 C 版本不支持初始化变量在 for 循环内。现在明显的解决方法是将初始化移到循环之外,代码如下:
// Doesn't work
#define MAP_FOREACH(key, val, map) \
struct _map_iterator iter __attribute__((cleanup(_map_iter_cleanup)));
for (; \
(key) = iter->pair->key, \
(value) = iter->pair->value; \
iter = iter->get_next_cb())
问题在于__attribute__((cleanup(_map_iter_cleanup))) 位。根据GCC documentation,它定义了附加到变量的清理代码,当变量超出范围时运行。因为我们将迭代器声明移到了 for 循环之外,所以它的范围发生了变化,并且清理代码在其他地方运行。不幸的是,库的其他部分依赖于立即清理迭代器 - 映射会跟踪已启动的迭代器数量,如果在它们全部消失之前被销毁,则会引发错误。
几天来,我一直在尝试并没有想出一个干净的方法,但我做不到。我真的不想在 C99 之前的代码中重新实现宏加清理,但是这个库到处都在使用,并且更改 API 以包含迭代后清理调用会很痛苦,而不是提到不雅。
有没有人遇到过这种事情并知道解决方法?
编辑:我们使用带有 -std=c89 选项的 GCC 4.2.2
【问题讨论】:
-
我有点惊讶有一个编译器不支持
-std=c99,但支持__attribute__((cleanup()))。这是什么编译器? -
哦,原来does支持C99。如果由于某种原因您不能在整个项目中使用 C99,为什么不只对有问题的文件使用它呢?
标签: c c-preprocessor c89