如何可靠地获得一个析构函数来覆盖缓冲区,而不需要在c++中对其进行优化



我正在查看其他人的代码,我在析构函数中看到他正在覆盖一个缓冲区,该缓冲区是类内的int数组。我想编译器可能会对此进行优化。

所以我做了一个小程序来测试,它确实优化了析构函数。

我发现的唯一简单的解决方案是在析构函数上使用属性((optimize("O0"((。但必须有一种方法可以做到这一点,而不使用gcc特定的属性。

我尝试过的东西:

  1. 将缓冲区设置为volatile——如果您直接在for循环中设置缓冲区(而不是memset或类似的(,这会起作用。但我真的不希望这是不稳定的,因为它不是。

  2. 属性((optimize("O0"(((工作,但不可移植,而且有点难看。

  3. 使用自己的内存池创建自己的新/删除。我在想,如果编译器不知道内存是如何使用的,它就不应该优化对内存的写入。事实上,这似乎是一个错误。

  4. 设置一个类,该类的唯一任务是覆盖其他内存中的缓冲区。这是有效的,但人是不必要的丑陋。

我想很多应用程序都想做这样的事情。不仅仅是调零关键点。肯定有人以前遇到过这个问题,或者我只是做错了什么。

想法?

g++memset.cpp-O1-fsanitize=未定义-Wall-Wextra

#include <stdio.h>
#include <string.h>
class example{
public:
int key[100];

~example(){
printf("destructorn");
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("ndeletedn");
print_memory(ptr->key);
printf("n");
}

输出:随机完成。

0:a:6bbb4567 1:a:327b23c6 2:a:643c9869 3:a:66348773 4:a:74b0dc51 5:a:19495cff 6:a:2ae8944a 7:a:625558ec 8:a:238e1f29 9:a:46e87ccd析构函数

已删除

0:a:0000000001:a:0000000002:a:0e57f010 3:a:0000555b 4:a:74b0dc51 5:a:19495cff 6:a:2ae8944a 7:a:625558ec 8:a:238e1f29 9:a:46e87ccd

一种裸机方式是通过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);
}

最新更新