注意:下面的文件都是.cpp文件或者.h文件, 没有.c文件。
先来看看有static情况
#include <stdio.h>
int fun()
{
static int i = 0;
i++;
return i;
}
int main()
{
int a = -1;
int b = -1;
a = fun();
printf("%d\n", a);
b = fun();
printf("%d\n", b);
return 0;
}
这个很简单, 两次调用fun, 得到的a和b是不一样的。
再看看看全局变量:
#include <stdio.h>
int g_n = -1;
int fun()
{
return g_n;
}
int main()
{
int a = -1;
int b = -1;
// 程序猿A在这里调用fun
a = fun();
printf("%d\n", a);
//程序猿C在这里写了一些复杂的代码
g_n = 100;
// 程序猿B在这里调用fun
b = fun();
printf("%d\n", b);
return 0;
}
这个也好理解, 全局变量嘛, 万恶之源。
再来看个:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int fun()
{
return rand();
}
int main()
{
int a = -1;
int b = -1;
a = fun();
printf("%d\n", a);
b = fun();
printf("%d\n", b);
return 0;
}
a和b的值不一样, 这种也很好理解。
类似这样的地方太多了, 都是不可重入的函数。
下面看看这个案例吧: 在某复杂系统中, 从某一时刻起, 比如说是set事件发生后, 模块A每次调用函数a, 都得到结果x, 模块B每次调用函数b, 都得到结果y. (x和y不相同)
简化一下原来的模型:
#include <stdio.h>
int g_n = 1;
void set()
{
g_n = 100;
}
int fun()
{
return g_n;
}
int main()
{
int a = -1;
int b = -1;
// A 模块
set(); // set事件发生后
a = fun();
printf("%d\n", a);
// B 模块
b = fun();
printf("%d\n", b);
return 0;
}
运行一下, 结果a, b都是100啊, 看来我模拟错了。
由于系统比较复杂, 相关进程比较多, 而且杂乱。 我当时看到A和B同时调用fun, 就误以为它们三者在同一个进程中, 是一个三口之家。 问了几个同事, 也没有想到是不同进程加载动态链接库fun造成的。我当时也没有意识到A模块和B模块属于不同的进程, 没有意识到fun函数是以动态链接库的形式存在的。
下面, 继续看:
动态库程序:
#include <stdio.h>
#include <windows.h>
int g_n = 1;
_declspec(dllexport) void set()
{
g_n = 100;
}
_declspec(dllexport) int fun()
{
printf("current pid is %ld\n", GetCurrentProcessId());
return g_n;
}
模块A: 设对应的.exe为tes1.exe
#include <stdio.h>
#include "myTest.h"
#pragma comment(lib, "Test.lib")
int main()
{
int a = -1;
printf("%d\n", fun());
set(); // 在某种情况下, 发生了set事件
while(1)
{
printf("%d\n", fun());
getchar();
}
return 0;
}
模块B:设对应的.exe为tes2.exe
#include <stdio.h>
#include "myTest.h"
#pragma comment(lib, "Test.lib")
int main()
{
int a = -1;
printf("%d\n", fun());
while(1)
{
printf("%d\n", fun());
getchar();
}
return 0;
}
现在, 在同一PC上, 同时运行test1.exe和test2.exe, 得到结果:
我们看到, 上述的set事件并没有改变B中的结果。 原因是, 它们是两个不同的进程, 从进程号便可以看出。
在这个问题上确实纠结良久, 找到原因并解决了它, 内心还是有点激动哈, 亦有不少收获。晚上奖励了自己一顿大餐。