C++中如何判断传入缓冲区是否有效?
How to judge whether the incoming buffer is valid in C++?
在我的函数中,内存指针及其大小作为参数传递:
int myFun(uintptr_t* mem_ptr, int mem_size) {
// Code here
}
有什么方法可以判断这块内存是否真的有效?
(操作系统为 CentOS Linux 7.9.2009 版。)
不要。只是不要。
即使您能找到一种方法来检查指针是否可以安全地取消引用,也不意味着它指向了您认为它指向的位置!它可能指向您的调用堆栈,指向您的 read-only 代码段,指向您正在使用的某些库的静态变量,或您的程序恰好可以访问的内存中的任何其他位置。
传递有效指针的责任应该由函数的调用者承担。为了让调用者更难做一些愚蠢的事情,考虑传递一个 std::vector &
或 std::vector const &
来代替。
很简单。不要写这样的代码。
就像您要检查的那样容易出错。这就是为什么现代 c++ 发明了例如 std::span。跨度代表连续的对象序列,就像您的指针 + 大小一样。但是指针和大小不是您可以在函数调用中轻易混淆的单独值。它是包含两者的单个对象。
实际上,如果大小在编译时已知,它会在类型本身中进行编码,并且跨度仅包含一个指针,使其更小并允许更好地优化函数。
除此之外,您还必须相信您函数的用户不会对您说谎。没有好的方法来验证指针,这是一个困扰垃圾收集器的问题,最好让 OS 通过产生段错误告诉您指针何时完全是垃圾。
注意:使用 span 而不是数组 make 比传递指针 + size 更简单:
#include <span>
int get(std::span<int> x, size_t i) {
return x[i];
}
int main() {
int x[] = {2, 3, 5, 7, 11};
return get(x, 2);
}
std::span
可以从已知大小的数组构造,因此编译器会为您完成所有工作。
在我的函数中,内存指针及其大小作为参数传递:
int myFun(uintptr_t* mem_ptr, int mem_size) {
// Code here
}
有什么方法可以判断这块内存是否真的有效?
(操作系统为 CentOS Linux 7.9.2009 版。)
不要。只是不要。
即使您能找到一种方法来检查指针是否可以安全地取消引用,也不意味着它指向了您认为它指向的位置!它可能指向您的调用堆栈,指向您的 read-only 代码段,指向您正在使用的某些库的静态变量,或您的程序恰好可以访问的内存中的任何其他位置。
传递有效指针的责任应该由函数的调用者承担。为了让调用者更难做一些愚蠢的事情,考虑传递一个 std::vector &
或 std::vector const &
来代替。
很简单。不要写这样的代码。
就像您要检查的那样容易出错。这就是为什么现代 c++ 发明了例如 std::span。跨度代表连续的对象序列,就像您的指针 + 大小一样。但是指针和大小不是您可以在函数调用中轻易混淆的单独值。它是包含两者的单个对象。
实际上,如果大小在编译时已知,它会在类型本身中进行编码,并且跨度仅包含一个指针,使其更小并允许更好地优化函数。
除此之外,您还必须相信您函数的用户不会对您说谎。没有好的方法来验证指针,这是一个困扰垃圾收集器的问题,最好让 OS 通过产生段错误告诉您指针何时完全是垃圾。
注意:使用 span 而不是数组 make 比传递指针 + size 更简单:
#include <span>
int get(std::span<int> x, size_t i) {
return x[i];
}
int main() {
int x[] = {2, 3, 5, 7, 11};
return get(x, 2);
}
std::span
可以从已知大小的数组构造,因此编译器会为您完成所有工作。