内存问题--全局变量被修改

本文描述了一起全局变量值莫名变为0的编程问题。通过分析,作者排除了变量被直接修改和对象销毁的可能性,最终发现是由于其他线程的堆内存分配导致全局变量内存被覆盖。通过调试定位,找到了问题的根源,提醒开发者注意编程规范,避免低级错误。

一、遇到的问题

1)情景说明:
我在一个类中定义了一个全局变量a,然后在类初始化的时候给该变量赋一个初始值a=10。该变量有被其他类外部引用,但是外部引用只是使用该值,并没有修改该值。然后在一个Timer中每秒打印这个变量1次。
2)看到的现象:
该变量a期初一直输出10,在突然的某一时刻,该值变成了 0

二、我所想到的问题的原因

我看到这种现象后,脑子不加思索的就想到以下两种原因:
1)肯定有人改变变量a的值。
答案是肯定的,只是在那个类初始化的时候给变量赋一次值,其它地方均没有。
2)要么是拥有该变量的对象被销毁了,所以其值就变成0了。
答案是很明显的,自习读题目就能发现,这种现象不可能发生,因为它是一个全局变量,不属于哪一个对象。

三、真正的原因

是由于其它线程中的某个对象malloc堆内存空间时,把全局区的变量的地址给占用了。。也就是堆空间把全局变量区的部分地址给占用了。

对此,我们做了一个测试:

char mycha[1024*10]; // 声明10K的空间
double a;

init(){
a = 10;
memset(mocha,'a',1024*10);
}

timer(){
    printf("%f",a);
    printf("%s",mycha);

    judge();
}


judge(){
    if(mycha[0] != 'a'){
        NSLog(@"发生了内存错误");
    }
}

我们通过打印发现:
mycha后来真的不是aaa……了,它真的被改变了。由于mycha和a的位置挨着,所以a得值发生变化,肯定也是其内存地址被别人给破坏掉了。

证实:
我们可以通过watch change(Xcode中debug功能)a变量,可以发现是哪个地方把a给变了。这样就能很好的定位了。

四、结语

可能非常棘手的问题(比如就这个问题,找了整整两天)是非常低级的错误造成的。所以,写代码的时候不能犯困,不能违背编程规范。

### 全局变量修改的原因 - **程序逻辑错误**:在函数内部未正确使用全局变量声明,可能导致意外修改全局变量。例如,在 Python 中,如果在函数内部直接对变量进行赋值操作,而没有使用 `global` 关键字声明,Python 会将其视为局部变量。若后续代码又对该变量进行引用和修改,可能会错误地改变全局变量的值。如下面的代码: ```python g_num = 0 def test2(): g_num = 0 g_num += 20 print("在test2里 g_num为:%d" % g_num) ``` 在 `test2` 函数中,`g_num` 被当作局部变量处理,虽然这里并没有真正修改全局的 `g_num`,但如果逻辑更复杂,可能会导致混淆和错误修改全局变量 [^3]。 - **全局变量字节未对齐**:全局变量字节未 4 字节对齐可能会导致其值被莫名其妙地改变。例如在调试时,发现一个变量定义成局部变量能正常运行,定义成全局变量就出现问题,且该变量未被其他函数使用,最后发现是其地址除以 4 不是整数,即未 4 字节对齐 [^2]。 - **编译器优化问题**:编译器在优化代码时,可能会对变量的存储和使用进行调整,从而导致全局变量的值被意外修改。当编译器进行寄存器分配和代码重排时,可能会错误地覆盖全局变量的值。 - **硬件故障**:硬件方面的问题,如内存故障、电路短路等,可能会导致全局变量所在的内存区域数据被意外修改- **外部干扰**:在一些特殊环境下,强电磁干扰、辐射等可能会影响计算机硬件的正常工作,进而导致全局变量的值被改变。 ### 解决方法 - **正确使用全局变量声明**:在需要修改全局变量的函数内部,使用相应语言的全局变量声明关键字。在 Python 中使用 `global` 关键字,示例如下: ```python g_num = 0 def test1(): global g_num g_num += 10 print("test1后 g_num为:%d" % g_num) ``` 这样可以确保在函数内部对 `g_num` 的修改是针对全局变量进行的 [^3]。 - **确保全局变量字节对齐**:对于因字节未对齐导致的问题,可以使用特定的语法使其 4 字节对齐。在某些编译器中,可以使用 `__attribute__((aligned(4)))` 修饰全局变量,示例如下: ```c int __attribute__((aligned(4))) global_variable; ``` - **调整编译器优化级别**:尝试降低编译器的优化级别,减少编译器对变量使用的重新安排。在使用 GCC 编译器时,可以使用 `-O0` 选项关闭优化: ```bash gcc -O0 your_program.c -o your_program ``` - **进行硬件检测和维修**:使用硬件检测工具对计算机硬件进行全面检测,找出故障部件并进行维修或更换。 - **采取抗干扰措施**:在存在强电磁干扰、辐射等特殊环境中,采取屏蔽、接地等抗干扰措施,减少外部干扰对硬件的影响。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值