当前位置: 首页 > news >正文

“解引用“空指针一定会导致段错误吗?

可能有些朋友看见这个标题第一反应是嵌入式的某些内存中,0地址也是可以被正常访问的,所以对0地址的解引用不会发生错误,但我要说的情况不是这个,而是指一个真正的空指针,不仅是c/c++中的0,(void*)0,NULL,还有nullptr,一个真正的空指针.

在c语言中,想获得某结构体的成员变量相对偏移,可以使用offsetof宏,其实现可能是:

#define offsetof(s,m)   (size_t)&(((s*)0)->m)

可以发现:

  1. 先将0转换为指向s的指针
  2. 使用->解引用,获取到m变量
  3. 使用&取地址,获得一个指向m的指针
  4. 将指针转换为size_t,即为m的偏移

从这个例子可以发现,对于0地址,发生了一次"解引用",然而并没有"segmentation fault",为什么呢?其实呢,这个解引用被优化了,编译器看到这句时,并没有发生实际的解引用而获得到了m的地址,是一个真正的编译器开洞才能实现的功能.(如有错误,诚请斧正)

你可以这样定义自己的offsetof

#undef offsetof
#define offsetof(s,m)	(size_t)&(((s*)NULL)->m)
// 或
#undef offsetof
#define offsetof(s,m)	(size_t)&(((s*)nullptr)->m)

你会发现,也是可以正常工作的,至少gcc的c++14之前是可以的,gcc的c++14后,
对于non-POD类型,这个宏将可能可能导致未定义的问题.注意,在cppreference中说的是从c++11开始,对于non-POD类型使用offsetof宏将导致未定义行为.
no-invalid-offsetof

gcc中的offsetof是这样定义的:Support for offsetof

#define offsetof(type, member) __builtin_offsetof (type, member)

可以发现,果然是内置的编译器开洞实现的功能.

综上,解引用一个空指针,不一定会导致段错误.
在c++中,想获得类或结构体成员的偏移量,不要使用offsetof,而应该使用&ClassName::MembersName,例如&test::str,就获取到了str的偏移

#include <vector>
#include <iostream>
class test{
public:float float_number = 3.14;int int_number = 456;std::string str = "789";
};template<typename T>
void print_member(const test* class_ptr,T test::* member_offset){printf("offset of member is %p,content is ",member_offset);std::cout << class_ptr->*member_offset << std::endl;
}int main(){test t;print_member(&t,&test::int_number);print_member(&t,&test::str);
}
/*
output:
offset of member is 0x4,content is 456
offset of member is 0x8,content is 789
*/
http://www.lryc.cn/news/123141.html

相关文章:

  • 釉面陶瓷器皿SOR/2016-175标准上架亚马逊加拿大站
  • Redux - Redux在React函数式组件中的基本使用
  • rust学习-同时执行多Future
  • 问道管理:旅游酒店板块逆市拉升,桂林旅游、华天酒店涨停
  • 算法通关村第三关——数组白银
  • 黑客利用 Facebook 漏洞,发起网络钓鱼攻击
  • React Router@3.x 升级到 @6.x 的实战
  • LAXCUS和GPU软硬件结合,构建强大算力生态
  • 学会这一招,轻松玩转小程序自动化
  • Mongodb 更新集合的方法到底有几种 (上) ?
  • 推荐5款能帮你解决各种问题的神器
  • 绕过 open_basedir
  • 如何使用SpringBoot 自定义转换器
  • 多线程(进阶)
  • 端口输入的数据为什么要打拍?
  • Qt读写Excel--QXlsx编译为静态库2
  • win11电脑查找已连接打印机ip的方法
  • 测试开发探索:“WeTalk“网页聊天室的测试流程与自动化
  • 图片增强组件实现
  • go.sum are different when using go mod vendor/download
  • Docker技术入门教程
  • Vue2-组件,组件的使用及注意点,组件嵌套,VueComponent构造函数,单文件组件
  • IntelliJ IDEA Bookmark使用
  • kriging-contour前端克里金插值
  • 第八章 CUDA内存应用与性能优化篇(中篇)
  • 适用于物联网 (IoT)的远距离、低功耗、低速率WiFi—Wi-Fi HaLow
  • 【解读Spikingjelly】使用单层全连接SNN识别MNIST
  • 穿越数字奇境:探寻元宇宙中的科技奇迹
  • 2024」预备研究生mem-阴影图形
  • 【设计模式】责任链模式