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();
在整个程序中使用驱动程序变量,直到它终止。
一些问题:
非常感谢任何建议,
答案 0 :(得分:3)
一般来说,没有。它使该功能不可重复。在代码作者真正知道他们在做什么的情况下,它可以在克制的情况下使用。
在外面声明它会使用struct对象的名称污染文件级命名空间。由于在其他任何地方都不需要直接访问对象,因此在函数内部声明它更有意义。没有其他区别。
在堆上分配?表现会受到影响。内存碎片会发生。调用者将承担明确释放内存的任务。当可以避免时强制用户使用动态内存通常不是一个好习惯。
可重构实现的更好的想法是从外部传递指向目标结构的指针。这样调用者就可以完全自由地以他们认为合适的方式分配收件人内存。
当然,你在这里看到的只是一个类似单身成语的C实现(很可能是,根据函数的名称来判断)。这意味着该函数应该每次都返回相同的指针,即所有调用者都应该通过返回的指针查看和共享相同的struct对象。并且,您可能甚至期望修改相同的对象(假设没有并发)。在这种情况下,您在此处看到的是全局变量的函数包装实现。所以,在这种情况下改变任何东西实际上会破坏目的。
答案 1 :(得分:3)
只要您意识到修改函数返回的指针的任何代码修改与获得相同指针所引用的任何其他代码相同的变量,这不是一个大问题。 “只要”可能是一个相当重要的问题,但它确实有效。它通常不是最佳实践 - 例如,返回指向单个静态变量的指针的asctime()
等C函数不像将结果放入用户提供的变量那样容易使用 - 特别是在线程代码中(函数不可重入)。但是,在这种情况下,看起来你正在实现Singleton模式;你可能只想要一份“驱动程序”副本,所以对我来说看起来很合理 - 但是我们需要更多关于用例的信息,然后才能说出“这是恶魔般的错误”。
这里的函数static和文件静态变量之间没有太大区别。不同之处在于实现代码(文件中的任何代码都可以访问文件静态变量;函数静态变量只能在一个函数中访问)而不能在消费者代码中访问。
'内存池'不是标准的C概念。通常,传递由被调用函数初始化的结构可能会更好,但它取决于上下文。就目前而言,出于设计的目的,它是可以的。
注意:代码最好写成:
driver_t *driver = driver_instance_get();
优化器可能无论如何都会优化代码,但是分配NULL然后立即重新分配是没有意义的。