英文:
Memset memory that will not be optimized away
问题
这与此问题相关:是否有一种方法可以在使用完缓冲区后(例如出于安全考虑)对其进行memset,而不会被优化掉?
尝试将指针强制转换为volatile指针,但会收到有关将volatile指针发送给不期望volatile的函数的警告。
英文:
This is related to this question: is there is a way to memset a buffer after finished using it (for security for example) without it being optimized out?
Trying to cast the pointer to volatile pointer getting warning about sending volatile pointer to function that not expects volatile.
答案1
得分: 5
The memset_explicit()
function from the C23 draft standard does what you want, but might not be implemented in current versions of the C standard library. The GNU Gnulib (GNU Portability Library) includes a version of memset_explicit()
that can be incorporated in a project's sources under the terms of the GNU Lesser General Public License. The initial import into a project assumes that the project uses Autoconf, so that could be a problem for projects that do not use Autoconf.
The Gnulib implementation of memset_explicit()
uses conditional compilation to implement the function in various ways, such as calling memset_s()
(if available), adding a memory barrier after a call to memset()
, or if none of those can be used, calling memset()
via a volatile function pointer. The use of a volatile function pointer involves defining and initializing a function pointer volatile_memset
like this:
void * (* const volatile volatile_memset) (void *, int, size_t) = memset;
Calls to memset()
through the volatile_memset
pointer will not be optimized away.
英文:
The memset_explicit()
function from the C23 draft standard does what you want, but might not be implemented in current versions of the C standard library. The GNU Gnulib (GNU Portability Library) includes a version of memset_explicit()
that can be incorporated in a project's sources under the terms of the GNU Lesser General Public License. The initial import into a project assumes that the project uses Autoconf, so that could be a problem for projects that do not use Autoconf.
The Gnulib implementation of memset_explicit()
uses conditional compilation to implement the function in various ways, such as calling memset_s()
(if available), adding a memory barrier after a call to memset()
, or if none of those can be used, calling memset()
via a volatile function pointer. The use of a volatile function pointer involves defining and initializing a function pointer volatile_memset
like this:
void * (* const volatile volatile_memset) (void *, int, size_t) = memset;
Calls to memset()
through the volatile_memset
pointer will not be optimized away.
答案2
得分: 0
一种完全可移植的方法,从C90到C23,是使用一个结构体包装器,然后声明一个volatile
结构体对象:
typedef struct
{
uint8_t buf[n];
} buf_t;
volatile buf_t buf = {0};
// 等同于memset(buf, 0, sizeof buf) 但不能被优化掉
...
static const buf_t final_settings = { ... };
// 一些你希望缓冲区最终具有的值
...
buf = final_settings;
// 等同于memset/memcpy 但不能被优化掉
这也规避了C中关于“访问volatile
对象”与“volatile
左值访问”的怪异/缺陷(在C23中也已修复)。
英文:
A fully portable version from C90 to C23 is to use a struct wrapper and then declare a volatile
struct object:
typedef struct
{
uint8_t buf [n];
} buf_t;
volatile buf_t buf = {0};
// equivalent to memset(buf, 0, sizeof buf) but can't be optimized out
...
static const buf_t final_settings = { ... };
// some values you wish the buffer to have in the end
...
buf = final_settings;
// equivalent to memset/memcpy but can't be optimized out
This also dodges the quirk/flaw in C regarding "access of volatile object" vs "volatile lvalue access" (also fixed in C23).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论