实例说明定义变量时为什么需要初始化

  项目中自己实现了一个简单的http客户端,测试时发现上传至服务器的数据发生了错误,排查问题发现,在http组包的代码中忘记对字符串临时变量进行初始化操作。

  写了如下测试代码:

//测试代码1:将未进行变量初始化操作的代码置于循环体中
#include <stdio.h>
#include <string.h>
int main()
{
    int i=20;
    while(i-->0)
    {
        char tmp[50];
        int int_test;
        if(19==i)
        {
            int_test=0;
            tmp[0]='\0';
        }
        printf("tmp:%s\nint_test:%d\n",tmp,int_test);
        char test[5]="";
        sprintf(test,"%d",i);
        strcat(tmp,test);
        int_test+=i;
    }
    return 0;
}

//测试代码1: 输出
tmp:
int_test:0
tmp:19
int_test:19
tmp:1918
int_test:37
tmp:191817
int_test:54
tmp:19181716
int_test:70
tmp:1918171615
int_test:85
tmp:191817161514
int_test:99
tmp:19181716151413
int_test:112
tmp:1918171615141312
int_test:124
tmp:191817161514131211
int_test:135
tmp:19181716151413121110
int_test:145
tmp:191817161514131211109
int_test:154
tmp:1918171615141312111098
int_test:162
tmp:19181716151413121110987
int_test:169
tmp:191817161514131211109876
int_test:175
tmp:1918171615141312111098765
int_test:180
tmp:19181716151413121110987654
int_test:184
tmp:191817161514131211109876543
int_test:187
tmp:1918171615141312111098765432
int_test:189
tmp:19181716151413121110987654321
int_test:190


//测试代码2 : 将未进行变量初始化操作的代码置于某函数体中
#include <stdio.h>
#include <string.h>
void just_for_test(int i)
{
    char tmp[50];
    int int_test;
    if(19==i)
    {
        int_test=0;
        tmp[0]='\0';
    }
    printf("tmp:%s\nint_test:%d\n",tmp,int_test);
    char test[5]="";
    sprintf(test,"%d",i);
    strcat(tmp,test);
    int_test+=i;
}

int main()
{
    int i=20;
    while(i-->0)
    {
        just_for_test(i);
    }
    return 0;
}

//测试代码2 : 输出 
tmp:
int_test:0
tmp:19
int_test:19
tmp:1918
int_test:37
tmp:191817
int_test:54
tmp:19181716
int_test:70
tmp:1918171615
int_test:85
tmp:191817161514
int_test:99
tmp:19181716151413
int_test:112
tmp:1918171615141312
int_test:124
tmp:191817161514131211
int_test:135
tmp:19181716151413121110
int_test:145
tmp:191817161514131211109
int_test:154
tmp:1918171615141312111098
int_test:162
tmp:19181716151413121110987
int_test:169
tmp:191817161514131211109876
int_test:175
tmp:1918171615141312111098765
int_test:180
tmp:19181716151413121110987654
int_test:184
tmp:191817161514131211109876543
int_test:187
tmp:1918171615141312111098765432
int_test:189
tmp:19181716151413121110987654321
int_test:190


//测试代码3 :观察局部变量调用地址
#include <stdio.h>
#include <string.h>
void just_for_test()
{
    static int call_times=0;
    int test=0;
    char tmp[5]="";
    printf("%d call %s --------\ntest's address : %p\ntmp's address : %p\n",call_times++,__func__,&test,tmp);
}
void just_for_test2()
{
    static int call_times=0;
    int test=0;
    char tmp[5]="";
    test+=2;
    (void) call_times;
    (void) test;
    (void) tmp;
}
int main()
{
    int i=10;
    while(i-->0)
    {
        just_for_test();
        if(0==i%3)
        {
            just_for_test2();
        }
    }
    return 0;
}

//测试代码3:输出1
0 call just_for_test --------
test's address : 0xbfac4af0
tmp's address : 0xbfac4af7
1 call just_for_test --------
test's address : 0xbfac4af0
tmp's address : 0xbfac4af7
2 call just_for_test --------
test's address : 0xbfac4af0
tmp's address : 0xbfac4af7
3 call just_for_test --------
test's address : 0xbfac4af0
tmp's address : 0xbfac4af7
4 call just_for_test --------
test's address : 0xbfac4af0
tmp's address : 0xbfac4af7
5 call just_for_test --------
test's address : 0xbfac4af0
tmp's address : 0xbfac4af7
6 call just_for_test --------
test's address : 0xbfac4af0
tmp's address : 0xbfac4af7
7 call just_for_test --------
test's address : 0xbfac4af0
tmp's address : 0xbfac4af7
8 call just_for_test --------
test's address : 0xbfac4af0
tmp's address : 0xbfac4af7
9 call just_for_test --------
test's address : 0xbfac4af0
tmp's address : 0xbfac4af7

//测试代码3 :输出2
0 call just_for_test --------
test's address : 0xbff3eb40
tmp's address : 0xbff3eb47
1 call just_for_test --------
test's address : 0xbff3eb40
tmp's address : 0xbff3eb47
2 call just_for_test --------
test's address : 0xbff3eb40
tmp's address : 0xbff3eb47
3 call just_for_test --------
test's address : 0xbff3eb40
tmp's address : 0xbff3eb47
4 call just_for_test --------
test's address : 0xbff3eb40
tmp's address : 0xbff3eb47
5 call just_for_test --------
test's address : 0xbff3eb40
tmp's address : 0xbff3eb47
6 call just_for_test --------
test's address : 0xbff3eb40
tmp's address : 0xbff3eb47
7 call just_for_test --------
test's address : 0xbff3eb40
tmp's address : 0xbff3eb47
8 call just_for_test --------
test's address : 0xbff3eb40
tmp's address : 0xbff3eb47
9 call just_for_test --------
test's address : 0xbff3eb40
tmp's address : 0xbff3eb47

//测试代码4:测试多线程函数调用局部变量值的变化
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
void just_for_test(int i)
{
    static int call_times=0;
    int test;
    if(call_times++==0)test=0;
    if(i==0)test=0;
    printf("test:%d **i(%d)*call_times(%d)*%p\n",test,i,call_times,&test);
    test+=i;
}
void print_now_time(const char *msg)
{
    struct timeval time_now;
    gettimeofday(&time_now,NULL);
    printf("sec:%lu usec:%lu \ninfo:%s\n",time_now.tv_sec,time_now.tv_usec,msg);
}

void * test_pthread(void *ptr)
{
    (void)ptr;
    int i=5;
    while(i-->0)
    {
        print_now_time("change it test to 0!");
        just_for_test(0);
        usleep(1000);
    }
    return NULL;
}
void run_test_pthread()
{
    pthread_t pid;
    pthread_create(&pid,NULL,test_pthread,NULL);
    pthread_detach(pid);
}
int main()
{
    int i=5;
    run_test_pthread();
    while(i-->0)
    {
        print_now_time("read test'value!");
        just_for_test(i);
        usleep(1000);
    }
    return 0;
}

//测试代码4 : 输出1
sec:1556181584 usec:21388 
info:read test'value!
test:0 **i(4)*call_times(1)*0xbfed23ec
sec:1556181584 usec:21568 
info:change it test to 0!
test:0 **i(0)*call_times(2)*0xb77f52ec
sec:1556181584 usec:22847 
info:change it test to 0!
test:0 **i(0)*call_times(3)*0xb77f52ec
sec:1556181584 usec:23247 
info:read test'value!
test:23247 **i(3)*call_times(4)*0xbfed23ec
sec:1556181584 usec:24116 
info:change it test to 0!
test:0 **i(0)*call_times(5)*0xb77f52ec
sec:1556181584 usec:25217 
info:read test'value!
test:25217 **i(2)*call_times(6)*0xbfed23ec
sec:1556181584 usec:25275 
info:change it test to 0!
test:0 **i(0)*call_times(7)*0xb77f52ec
sec:1556181584 usec:27853 
info:read test'value!
test:27853 **i(1)*call_times(8)*0xbfed23ec
sec:1556181584 usec:27882 
info:change it test to 0!
test:0 **i(0)*call_times(9)*0xb77f52ec
sec:1556181584 usec:30522 
info:read test'value!
test:0 **i(0)*call_times(10)*0xbfed23ec

//测试代码4 : 输出2
sec:1556181911 usec:172708 
info:read test'value!
test:0 **i(4)*call_times(1)*0xbfdf61fc
sec:1556181911 usec:172752 
info:change it test to 0!
test:0 **i(0)*call_times(2)*0xb77e42ec
sec:1556181911 usec:175377 
info:change it test to 0!
test:0 **i(0)*call_times(3)*0xb77e42ec
sec:1556181911 usec:175563 
info:read test'value!
test:175563 **i(3)*call_times(4)*0xbfdf61fc
sec:1556181911 usec:177801 
info:change it test to 0!
test:0 **i(0)*call_times(5)*0xb77e42ec
sec:1556181911 usec:177932 
info:read test'value!
test:177932 **i(2)*call_times(6)*0xbfdf61fc
sec:1556181911 usec:180286 
info:change it test to 0!
test:0 **i(0)*call_times(7)*0xb77e42ec
sec:1556181911 usec:180520 
info:read test'value!
test:180520 **i(1)*call_times(8)*0xbfdf61fc
sec:1556181911 usec:182776 
info:change it test to 0!
test:0 **i(0)*call_times(9)*0xb77e42ec
sec:1556181911 usec:182911 
info:read test'value!
test:0 **i(0)*call_times(10)*0xbfdf61fc

从前面的三个测试样例可以得出一个结论,局部变量的存储地址在函数加载时已经被确定。

从第四个测试样例中可以发现,当调用环境复杂时,局部变量上次存储的值不再被保留至下次调用,说明这块地址可能被另一个量使用并修改过,不同线程会保存一个函数副本,共享静态存储变量

故可能被多次调用的函数体需要对所有使用的局部变量进行初始化操作,防止局部变量对应存储区域的值不符合要求影响到程序输出。

猜你喜欢

转载自blog.csdn.net/xuyuanwang19931014/article/details/89517390
今日推荐