3

C89 gcc (GCC) 4.7.2

你好,

我正在维护某人的软件,我发现这个函数返回静态结构的地址。这应该没问题,因为静态表示它是全局的,因此结构的地址将可用,直到程序终止。

DRIVER_API(driver_t*) driver_instance_get(void)
{
    static struct tag_driver driver = {
    /* Elements initialized here */
    };

    return &driver;
}

像这样使用:

driver_t *driver = NULL;
driver = driver_instance_get();

驱动程序变量在整个程序中使用,直到它终止。

一些问题:

  1. 这样做是个好习惯吗?
  2. 在文件级别的函数之外声明它有什么区别吗?
  3. 为什么不将内存池传递给函数并为结构分配内存,以便在堆上声明结构?

非常感谢您的任何建议,

4

2 回答 2

3
  1. 一般来说,没有。它使函数不可重入。在代码作者真正知道自己在做什么的情况下,可以有节制地使用它。

  2. 在外部声明它会用结构对象的名称污染文件级命名空间。由于在其他任何地方都不需要直接访问该对象,因此在函数内声明它更有意义。没有其他区别。

  3. 在堆上分配?性能会受到影响。会发生内存碎片。调用者将承担显式释放内存的任务。在可以避免的情况下强制用户使用动态内存通常不是一个好习惯。

    可重入实现的一个更好的想法是从外部传递一个指向目标结构的指针。这样,调用者就可以完全自由地以他们认为合适的任何方式分配接收者的内存。


当然,您在这里看到的可能只是一个类似单例的习语的 C 实现(从函数的名称来看,很可能是这样)。这意味着函数应该每次都返回相同的指针,即所有调用者都应该通过返回的指针看到并共享相同的结构对象。而且,您甚至可能期望修改同一个对象(假设没有并发)。在这种情况下,您在此处看到的是全局变量的函数包装实现。因此,在这种情况下更改此处的任何内容实际上会破坏目的。

于 2013-05-09T14:49:11.257 回答
3
  1. 只要您意识到修改函数返回的指针的任何代码都在修改与获得相同指针的任何其他代码所引用的变量相同的变量,这不是一个大问题。“只要”可能是一个相当重要的问题,但它确实有效。这通常不是最佳实践——例如,asctime()返回指向单个静态变量的指针的 C 函数不像那些将结果放入用户提供的变量的函数那样容易使用——尤其是在线程代码中(该函数不可重入)。但是,在这种情况下,您似乎正在实现单例模式;你可能只想要一份“驱动程序”,所以对我来说这看起来很合理——但我们需要更多关于用例的信息,然后再高谈阔论“

  2. 这里的函数静态变量和文件静态变量之间并没有太大区别。区别在于实现代码(文件中的任何代码都可以访问文件静态变量;函数静态变量只能在一个函数中访问)而不是在消费者代码中。

  3. “内存池”不是标准的 C 概念。一般来说,传入要由被调用函数初始化的结构可能会更好,但这取决于上下文。就目前而言,就其设计目的而言,它是可以的。

注意:代码最好写成:

driver_t *driver = driver_instance_get();

无论如何,优化器可能会优化代码,但是分配 NULL 然后立即重新分配是没有意义的。

于 2013-05-09T14:52:25.700 回答