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

时间:2013-10-03 08:30:55

标签: c static

在一个更大的项目中,我要写一个C函数列表,它们在同一个内存结构上工作。 由于这些函数在代码的非常不同的部分中调用(并且在不同的库中被单独编译然后链接),我想避免必须将指针作为参数传递给内存结构作为每个函数调用的参数。 / p>

我正在考虑将内存结构作为静态变量存储在单个函数中,并始终在其他函数中调用该函数以获取指向内存结构的指针。 在下面的示例中,我使用storage()来设置sto指针。

我测试了下面的代码,似乎工作正常。这是标准方法吗?我跑的风险是什么?这会一直有效吗?更好的解决方案?

我的功能没有并发调用。当然我也可以释放分配的内存。

#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作为参数意味着在项目主体中声明一个指针并更改大量核心嵌套函数,这些函数与我的函数执行的任务无关,以传递附加参数。

此外,同一组功能将被集成到多个略有不同的项目中,因此不那么干扰的集成,必须尽可能少地修改外部代码,将是一个加号。

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

是否仍然没有选择,只是更改所有功能以在项目周围携带sto

3 个答案:

答案 0 :(得分:2)

这有几个缺点

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

第二,它充当全局值,最好使用指针在函数之间传递数据,因为它使得它更清晰 - 从可读性的角度来看 - 哪个函数通过查看函数原型来访问数据:

void foo(storage* p);
void foo1();
void foo2(const storage* p);

第三,您在访问数据时增加了开销

您的存储功能中也存在内存泄漏,您将sto声明为静态,但在将其分配给malloc之前不检查它是否已指向某个内容。

static int* sto;
if (get_set==1)
{
    sto=malloc(2*sizeof(int));
    sto[0]=1;
    sto[1]=2;
}

应该是

static int* sto;
if (get_set==1)
{
    if ( sto != NULL ) 
    {
      free(sto);
    }
    sto=malloc(2*sizeof(int));
    sto[0]=1;
    sto[1]=2;
}

如果您仍然坚持使用此方法,您至少应该将值放在结构中,然后将复制值,并且您不需要每次都分配堆(缺点是更多开销)。

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;
}

答案 1 :(得分:2)

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

第一种方法:

包含数据的模块:

static int mydata; /* note: "static" */

int* accessor() {
    return &mydata;
}

模块使用数据:

int* accessor();

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

第二种方法:

包含数据的模块:

int mydata; /* note: no "static" */

模块使用数据:

extern int mydata; /* note: "extern" */

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

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

答案 2 :(得分:0)

这肯定不是标准做法,并为您的代码增加了一定程度的可读性问题。想象一下,刚刚添加到您的项目中的人现在需要使用此代码,他/她会非常困惑。此外,每个函数调用都可能导致一些开销,因此将指针传递给所有函数会更好。