【问题标题】:Variable inside .c changing value incorrectly.c 中的变量错误地更改值
【发布时间】:2014-11-19 11:09:46
【问题描述】:

我遇到了一个非常奇怪的问题,即变量在我的 C 代码中错误地更改了它们的值。我在这个项目的 Qt Creator 中使用 GCC。

我有一个带有 main.c 文件的通用 C 项目,除其他文件外,还有两对 .c 和 .h(battery_general.c/.h 和 fpga_gps.c/.h)。电池和 GPS 系统都需要在计时器事件中定期调用“超时”方法(我实际上为此使用了 while(1)sleep(1))。在电池和 GPS 的超时功能中,我有一个名为 timeoutCounter 的 uint16_t 计时器,它在 timeout() 函数被调用时递增,直到 120,当它们的值重置为 0 时。这个“timeoutCounter”整数 是在每个各自的.c 文件 的全局范围内声明,并且它们无权访问彼此的内容。只有在main.c 中才包含两个 .h,所以我可以调用 timeout() 函数。

在 while 循环内的调用逻辑中,电池 timeout() 在 GPS 之前调用,并且在调用 GPS 的 timeout() 函数之前,电池的 timeoutCounter 被置为 0。

发生的情况是,当调用 GPS 超时时,它的 timeoutCounter(以值 121 开始)在第一次使用时设置为 0 - 自那时以来它应该为 121 的位置尚未对其值进行修改。就好像分配给电池timeoutCounter 的0 会影响GPS .c 文件中的timeoutCounter,即使它们彼此没有连接!因为当我更改 GPS 的 .c 文件中的 timeoutCounter(例如更改为 gpsTimeoutCounter)时,错误消失了!

可能是 GCC 错误地认为这两个变量是相同的,即使我没有使用 extern 并且文件不相关(它们之间没有#include)只是因为它们是相同的类型并且有相同的名字吗?它确实看起来像 GCC 中的一个错误!

无论如何,会发生什么?如果需要代码,我会发布一些,但所有相关的内容都已描述。我做了很多测试(全局搜索、调试等)来验证两个 .c 文件之间是否错误地建立了某种连接,但没有找到任何东西。我很伤心:我只是更改了其中一个变量的名称,错误消失了,如果我将两个变量都更改为不同的相同名称(例如,两者都称为gpsTimeoutCounter),错误再次出现!

【问题讨论】:

  • 您是否使用了调试器(所以使用gcc -Wall -g 编译,然后使用gdb)。您应该在gdb 中使用观察点
  • @ericbn 虽然我会说我的问题不是重复的,但您提供的链接似乎确实谈到了同样的问题 - 这对我理解情况很有用。谢谢!

标签: c gcc variable-assignment


【解决方案1】:

是的,如果不同文件中的全局变量具有相同的名称,gcc 可以将它们视为相同的符号。这发生在链接阶段,当您有两个从不同源 .c 文件生成的对象 .o 文件时,它们都声明了一个具有相同名称的“外部”(全局)定义。

即使您不在标题 .h 文件中使用 extern,我也会发生这种情况。这只是为了告诉编译器和链接器 extern(它的意思是“外部链接”)定义已在别处声明(因此无需为该定义分配更多空间,它已经声明过)。

【讨论】:

  • 所以,你实质上是说,如果我声明两个同名的全局变量,即使它在两个不同且特定的.c(不是 main.c)中并且没有extern 与它们中的任何一个相关联,C 仍然会认为我在谈论同一个变量吗?好像我两次声明同一个变量?但是如果它知道我两次声明了同一个变量,那为什么不显示警告呢?
  • 是的,这就是我要说的。这取决于链接器,但它应该会给你一个警告,如 multiple definition of ...first defined here
  • 好吧,这无疑对我有负面影响,因为当我有这两个具有相同标识符的变量时,链接器不会提供任何警告 =T 如果给出警告,我可能会想出来很快。感谢您的回答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 2019-06-21
  • 1970-01-01
  • 2021-03-16
  • 1970-01-01
相关资源
最近更新 更多