首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >存储在一个函数静态变量中的函数共享的内存

存储在一个函数静态变量中的函数共享的内存
EN

Stack Overflow用户
提问于 2013-10-03 08:30:55
回答 3查看 408关注 0票数 1

在一个较大的项目中,我将编写一个C函数的列表,这些函数工作在相同的内存结构上。由于这些函数在代码的非常不同的部分中调用(以及在不同的库中分别编译,然后链接),因此我希望避免将指向内存结构的指针作为参数传递给每个函数调用。

我想把内存结构作为一个静态变量存储在一个函数中,并且总是在我的其他函数中调用这个函数,以获得一个指向内存结构的指针。在下面的示例中,我使用storage()来设置sto指针。

我测试了下面的代码,它似乎运行良好。这是一种标准做法吗?我在冒什么风险?这一切都会成功吗?更好的解决方案?

对我的函数没有并发调用。当然,我也会释放分配的内存。

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>

int* storage(int get_set)
{
    static int* sto;
    if (get_set==1)
    {
        sto=malloc(2*sizeof(int));
        sto[0]=1;
        sto[1]=2;
    }
    printf("storage: content = %d %d, pointer= %d\n", sto[0], sto[1], sto);
    return sto;
}

void add11()
{
    int* sto =storage(0);
    sto[0]+=1;
    sto[1]+=1;
    printf("add11: content = %d %d, pointer= %d \n", sto[0], sto[1], sto);
}

void multo0()
{
    int* sto =storage(0);
    sto[0]=sto[1]*sto[0];
    sto[1]=0;
    printf("multo0: content = %d %d, pointer= %d\n", sto[0], sto[1], sto);
}


int main(void) {
    storage(1); // initialize memory only once
    add11();  // work on memory 
    multo0();
    add11();
    // ...
    return 0;
}

我之所以想要这样的东西,原因如下:

我正在编写的一组函数执行单独的和辅助的可选的图像增强任务,并以不同的方式学习以前观察到的图像。sto为这种学习和参数化选项存储内存。

在整个项目中,我的函数将在多个嵌套函数调用中调用。将sto作为参数传递意味着在项目主体中声明a指针,并更改大量与函数执行的任务无关的核心嵌套函数,以传递附加参数。

此外,同一组函数将集成在多个略有不同的项目中,因此,一个较少的侵入性集成,必须尽可能少地修改外部代码,将是一个好处。

对于可读性问题,所有访问共享内存的函数都具有相同的前缀。我知道这不是完全的解决方案,但我相信它增加了一点可读性。

除了改变所有函数以使sto在整个项目中运行之外,是否仍然没有其他选项?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-03 08:45:31

由于您已经有多个要链接在一起的模块,所以“更标准”的方法应该是有一个静态(对单个模块私有)变量(第一种方法),如果您需要访问器函数,则返回一个指向该变量的指针。但是,如果访问器只返回指向它的指针,您可以简单地使用"extern“并以自然的方式访问数据(第二种方法)。

第一种方法:

包含以下数据的模块:

代码语言:javascript
运行
复制
static int mydata; /* note: "static" */

int* accessor() {
    return &mydata;
}

使用数据的模块:

代码语言:javascript
运行
复制
int* accessor();

int main() {
    int* foo = accessor();
}

第二种方法:

包含以下数据的模块:

代码语言:javascript
运行
复制
int mydata; /* note: no "static" */

使用数据的模块:

代码语言:javascript
运行
复制
extern int mydata; /* note: "extern" */

int main() {
    int* foo = &mydata;
}

第二种方法是“更多的C-ish”和更快。注意,通常的方法是在第二种情况下简单地使用"mydata“,就好像它是一个正常的局部变量,而不是仅仅为了指针而引入指针--我在这里这样做是为了与第一种情况一致。

票数 2
EN

Stack Overflow用户

发布于 2013-10-03 08:37:28

这有几个缺点

首先,函数每次调用时都会分配内存,但是调用方需要从函数的名称中显式释放返回的内容,这是不清楚的。

其次,它充当一个全局值,最好使用指针在函数之间传递数据,因为从可读性的角度看,哪个函数通过查看函数原型来访问数据比较清楚:

代码语言:javascript
运行
复制
void foo(storage* p);
void foo1();
void foo2(const storage* p);

第三,当您访问数据时会增加开销。

您的存储函数中也有内存泄漏,您声明sto为静态的,但是在将它分配给malloc之前,不要检查它是否已经指向某个东西。

代码语言:javascript
运行
复制
static int* sto;
if (get_set==1)
{
    sto=malloc(2*sizeof(int));
    sto[0]=1;
    sto[1]=2;
}

应该是这样的

代码语言:javascript
运行
复制
static int* sto;
if (get_set==1)
{
    if ( sto != NULL ) 
    {
      free(sto);
    }
    sto=malloc(2*sizeof(int));
    sto[0]=1;
    sto[1]=2;
}

如果您仍然坚持使用此方法,则至少应该将这些值放在结构中,那么这些值将被复制,并且不需要每次都分配堆(缺点是增加一些开销)。

代码语言:javascript
运行
复制
typedef struct
{
  int a[2];
} storage_ret;

storage_ret storage(int get_set)
{
    static storage_ret sto;
    if (get_set==1)
    {
        sto.a[0]=1;
        sto.a[1]=2;
    }
    printf("storage: content = %d %d, pointer= %d\n", sto.a[0], stoa.[1], &sto);
    return sto;
}
票数 2
EN

Stack Overflow用户

发布于 2013-10-03 08:34:00

这当然不是标准实践,而且会给代码增加一定程度的可读性。假设有人刚刚添加到您的项目中,现在需要使用这段代码,他/她会非常困惑。而且,每个函数调用都可能导致一些开销,因此最好传递一个指向所有函数的指针。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19154383

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档