gcc 在c++中如何可靠地让析构函数覆盖缓冲区而不优化它

cgyqldqp  于 2022-12-29  发布在  其他
关注(0)|答案(1)|浏览(129)

我在看别人的代码,我看到在析构函数中,他覆盖了一个缓冲区,这个缓冲区是类中的一个整型数组,我想编译器可能会优化它。
所以我做了一个小程序来测试,它确实优化了析构函数。
我找到的唯一简单的解决方法是在析构函数上使用attribute((optimize("O0"))),但是必须有一种方法可以在不使用gcc特定属性的情况下做到这一点。
我尝试过的事情:
1.将缓冲区设置为volatile--如果直接在for循环中设置缓冲区(而不是memset之类的),这是可行的,但我真的不希望它是volatile,因为它不是。
1.* * attribute**((optimize("O0")))可以工作,但不可移植,而且有点难看。
1.用它自己的内存池创建我自己的new/delete。我在想,如果编译器不知道内存是如何使用的,它就不应该优化对它的写入。事实上,这不起作用似乎是一个bug。
1.设置一个类,它的唯一工作就是覆盖另一个内存中的缓冲区。这是可行的,但人类是不必要的丑陋。
我想很多应用程序都想做这样的事情。不仅仅是把键清零。肯定有人以前遇到过这个问题,或者我只是做错了什么。
想法?
g ++ memset.cpp-O1-消毒=未定义-壁-额外

#include <stdio.h>
#include <string.h>
class example{
public:
  int key[100];
  
  ~example(){
    printf("destructor\n");
    memset(key,0, sizeof(key));
  }
};

void print_memory(int *in){
  printf ("\n");
  for(int i =0; i < 10; i++){
    printf(" %2d:a: %08x ",i, in[i]);
  }
}

int main(){
  example *ptr;
  {
    example *it = new example;
    ptr = it;
    // fill memory with something.
    for(int i = 0; i< 100; i++){
      it->key[i] = rand();
    }
    
    printf("Done randomizing.\n");
    print_memory(it->key);
    delete it;
  }
  printf("\ndeleted\n");
  print_memory(ptr->key);
  printf("\n");
}

输出:完成随机化。
0:a:6b8b4567 1:a:327b23c6 2:a:643c9869 3:a:编号66334873 4:a:74b0dc51 5:a:19495cff第6章a节:2ae8944a 7:a:625558ec 8:一种:238e1f29 9:a:46e87ccd析像管
删除
0:a:00000000 1:a:00000000 2:a:0e57f010 3:a:0000555b 4:a:74b0dc51 5:a:19495cff第6章a节:2ae8944a 7:a:625558ec 8:一种:238e1f29 9:a:46e87电荷耦合器件

tzxcd3kk

tzxcd3kk1#

一种裸机方式是通过volatile访问它--这样它就不会被优化。一种C方式是:

#include <cstddef>
void volatile_memset(volatile void *s, int c, size_t n) {
    volatile unsigned char *m = reinterpret_cast<volatile unsigned char *>(s);
    while (n--) {
       *m++ = c;
    }
}
int main() {
    char key[200];
    volatile_memset(key, 0, sizeof(key));
}

但我认为在C++中你可以:

#include <algorithm>
int main() {
    char key[200];
    std::fill_n<volatile char *>(key, sizeof(key)/sizeof(*key), 0);
}

或:

#include <algorithm>
#include <array>
int main() {
    char key[200];
    std::fill<volatile char *>(std::begin(key), std::end(key), 0);
}

相关问题