0

我在 STVD ide 中使用COSMIC 编译器,即使使用-no关闭了优化(文档说“-no:不要使用优化器”),一些代码行被删除并且不能在它们上放置断点,也不是它们可以在拆卸中找到。

我尝试设置 -oc (将已删除的指令保留为注释),这导致甚至没有将已删除的行显示为注释。

bool foo(void)
{
   uint8_t val;

   if (globalvar > 5)
      val = 0;

   for (val = 0; val < 8; val++)
   {
      some code...
   }

   return true;
}

val我知道在 for 循环之前设置为 0似乎很愚蠢,但让我们假设出于某种原因这是必要的。当我没有设置优化时,我希望它不会被优化,而是val = 0;会被删除而没有任何痕迹。

我不是在寻找一种解决方法,比如声明valvolatile whitch 可以解决问题。我宁愿寻找一种方法来防止优化,或者至少了解/知道在编译时对我的代码进行了哪些更改。

4

2 回答 2

0

手册中并不清楚,但似乎 -no 选项会阻止程序集级别的优化。在汇编优化之前运行的代码生成器阶段似乎有可能执行更高级别的优化,例如冗余代码删除。

从手册:

-cp

禁用常量传播优化。默认情况下,当为变量分配常量时,对该变量的任何后续访问都会被常量本身替换,直到变量被修改或遇到流中断(函数调用、循环、标签...)。

您似乎必须明确禁用这种持续传播功能。

这可能很不寻常,但似乎该编译器默认优化,并区分编译器优化和汇编器优化(作为编译阶段执行),它们使您可以分别关闭每个单独的优化。

为了避免在代码中出现这种情况,而不是全局关闭它,您可以val在这种情况下初始化为非零值:

int val = -1 ;

然后后面的赋值为零将需要显式代码。这可能具有优势volatile,因为当您启用优化时它不会阻止优化。

于 2019-08-13T19:29:06.377 回答
0

我相信 C 语言规范允许这种行为。

您实际上是在连续的代码行中将相同的值写入同一变量一次或两次。编译器可以在它认为合适的情况下将此值分配给处理器寄存器或内存位置,并且知道在 for 循环中初始分配之后的值与执行 if 子句时分配的值相同。因此,语言规范允许编译器丢弃冗余代码。

强制编译器对变量执行所有读写访问的方法是使用 volatile 关键字。这就是它的用途。

于 2019-08-14T08:26:51.883 回答