.NET跨平台实践:用C#开发Linux守护进程_3

背景:


阅读新闻

.NET跨平台实践:用C#开发Linux守护进程

[日期:2016-04-05]

来源:Linux社区

作者:宇内流云

[字体:大 中 小]

Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作。

一句话,为Linux开发与控制台无关的,需要在后台长时间不间断运行的“服务程序”,Daemon技术是非常重要的。

Daemon程序一般用c/c++开发。不过,我今天要讲的,不是怎么用c/c++开发daemon,而是用C#!

一,创建Daemon程序:

用VS新建一个控制台项目,假设名称是MyDaemon,输入下边的代码:

using System.Runtime.InteropServices;

using System.Threading;

namespace MyDaemon

{

class Program

{

static void Main(string[] args)

{

int pid= fork();

if (pid !=0) exit(0);

//设置“会话组长”,与父进程脱离

setsid();

pid = fork();

if (pid !=0) exit(0);

//已经进程“守护进程”工作状态了!

//关闭所有打开的文件描述符

int max=open("/dev/null", 0);

for (var i=0; i <=max; i++) { close(i); }

//重设文件掩模

umask(0);

//执行你的程序过程

DaemonMain(args);

}

///

/// Daemon工作状态的主方法

///

///

static void DaemonMain(string[] aargs)

{

//你的工作代码...

//daemon时,控制台输入输出流已经关闭

//请不要再用Console.Write/Read等方法

//阻止daemon进程退出

while (true)

{ Thread.Sleep(1000); }

}

[DllImport("libc", SetLastError=true)]

static extern int fork();

[DllImport("libc", SetLastError=true)]

static extern int setsid();

[DllImport("libc", SetLastError=true)]

static extern int umask(int mask);

[DllImport("libc", SetLastError=true)]

static extern int open([MarshalAs(UnmanagedType.LPStr)]string pathname, int flags);

[DllImport("libc", SetLastError=true)]

static extern int close(int fd);

[DllImport("libc", SetLastError=true)]

static extern int exit(int code);

}

}

然后编译为 MyDaemon.exe。

二,部署和运行:

.net 程序在linux运行,一般都会使用mono这个.net框架,不过,为了简单方便,我这里使用 AnyExec来运行这个程序(关于AnyExec,请参阅:不装mono,你的.NET程序照样可以在Linux上运行!)。

1,把 MyDeamon.exe放到anyexec的app文件夹;

2,把 "any"这个程序复制为 MyDeamon;

3,运行:见证神奇的时间到了!请你在linux控制终端上输入: http://www.linuxidc.com/Linux/2016-04/MyDaemon,哈哈,怎么没有反应? 其实,不是没有反应,是你这个 MyDaemon程序已经在后台跑起来了!

输入 “ps -ef”,看看!

看到那个 MyDaemon了吧!这次运行的PID是11618,父进程是的PID是1,1是谁?linux init!

4,退出daemon程序:daemon程序不会与控制台输入输出进行交互,所以,用Console.ReadLine之类的方法控制进程的退出是不现实的。那么,怎么关闭这个在后台运行的 daemon呢? 最简办法就是用ps -ef查出这个进程的PID号,然后用kill命令终止它。比如当前运行的这个 mydaemon的PID号是 11618,你只需要输入 kill -9 11618,就能终止它的运行。

(本文为宇内流云原创,经查,暂没发现网上有类似的技术文章,欢迎转载,但不要把作者的名字给弄丢了)

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-04/129842.htm

linux

Swift函数和闭包

JVM-类加载机制

相关资讯

Linux守护进程 C#开发Linux守护进程

Linux守护进程 (09/19/2015 15:01:04)

Linux下的守护进程 (01/25/2015 11:46:45)

Linux系统守护进程详解ntsysv 可以 (09/29/2013 08:57:56)

Linux 的进程组、会话、守护进程 (04/04/2015 11:16:46)

Linux守护进程学习 (01/04/2014 19:15:04)

Linux编程---守护进程 (01/04/2013 09:35:30)

本文评论

查看全部评论 (0)

表情: 表情

姓名:

匿名

字数

同意评论声明

评论声明

尊重网上道德,遵守中华人民共和国的各项有关法律法规

承担一切因您的行为而直接或间接导致的民事或刑事法律责任

本站管理人员有权保留或删除其管辖留言中的任意内容

本站有权在网站内转载或引用您的评论

参与本评论即表明您已经阅读并接受上述条款

最新资讯

CentOS 6.4下双网卡bond配置

CentOS6.x双网卡采用主-备份策略绑定(bond

ORA-30036故障解决方法案例

ORA-03114: 未连接到 ORALCE 解决方法案例

Oracle RAC系统内存无法释放解决

Oracle Goldengate在HP平台裸设备文件系统

OGG升级运行ggsic报Unable to find library

Linux vi命令大全

VMware虚拟机主机模式下与主机互ping通

Linux内核中container_of函数详解

背景:

阅读新闻

JVM-类加载机制

[日期:2016-04-05]

来源:Linux社区

作者:lrh-xl

[字体:大 中 小]

虚拟机类加载机制

虚拟机把描述的类的数据从class文件加载到内存后,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。

类加载的时机

类被加载到虚拟机内存开始,到卸载出内存为止。它的整个生命周期包括:类加载(Loading),验证(Verification),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using)和卸载(Unloading)7个阶段。其中验证,准备,解析3个部分统称为连接(Linking)。

虚拟机规范严格规定了有且仅有5种情况必须立即对类进行“初始化”:

1.遇到new , getstatic , putstatic 或involvestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。

2.使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。

3.当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。

4.当虚拟机启动时,用户需要指定一个要执行的主类(包含main方法的类),虚拟机会先初始化这个类。

5.当使用JDK1.7的动态语言支持时,如果java.lang.invoke.MethodHeadle实例,最后的解析结果REF_getstatic , REF_putstatic , REF_invokestatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。

类加载的过程

一、加载

(1)在加载阶段,虚拟机需要完成以下3件事:

1.通过一个类的全限定名来获取定义此类的二进制字节流

2.将这个字节流所代表的静态存储结构结构转化为方法区的运行时数据结构

3.在内存中生成一个代表这个类的java.lang.class对象,作为方法区这个类的各种数据的访问入口

(2)数组类本身不通过类加载器创建,他是由Java虚拟机直接创建的。

一个数组类创建过程遵循以下规则:

1.如果数组的组件类型(Component Type , 指的是数组去掉一个维度的类型)是引用类型,那就递归采用上面介绍的加载过程去加载这个组件类型,数组将在加载该数组组件类型的类加载器的类名称空间上呗标识。

2.如果数组的组件类型不是7引用类型,Java虚拟机将会把数组标记为与引导类加载器关联。

3.数组类的可见性与它的组件类型的可见性一致,如果组件类型不是引用类型,需要数组类的可见性将 默认为public

二、验证

验证是连接阶段的第一步,这一阶段的目的是为了确保class文件的字节流包含的信息符合当前虚拟机的要求,并且不会危害虚拟机本省的安全。

验证阶段大致上会完成以下4个阶段的检验动作:文件格式验证、元数据验证、字节码验证、符号引用验证

(1 ) 文件格式验证

1.第一阶段要验证字节流是否符合class文件格式的规范,并且能被当前版本的虚拟机处理。

2.中油通过了这个阶段的验证后,字节流才会进入内存的方法区中进行存储,所以后面的3个验证阶段全部是基于方法区的存储结构进行的,不会直接操作字节码。

(2 ) 元数据验证

1.第二阶段是对字节码描述的信息进行语义分析,以确保其描述的信息符合Java语言规范的要求。

2.第二阶段的主要目的是对类的元数据信息进行语义化验,保证不存在不符合Java语言规范的元数据信息

(3 ) 字节码验证

1.督三阶段是整个验证过程中最复杂的一个阶段,主要目的是通过数据流和控制流分析,确定程序语义是合法的,符合逻辑的。这个阶段将对类的方法体进行校验分析。保证被校验类的方法运行时不会做出危害虚拟机安全的时间。

2.例如:保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作。保证跳转到方法体以外的字节码指令上。

(4 ) 符号引用验证

1.最后一个验证阶段的检验发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在连接阶段的第三阶段——解析阶段中发生。符号引用验证可以看做是对类自身以外的信息进行匹配性校验。

2.例如:符号引用中通过字符串描述中的全限定名是否能找到对应的类。在特定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段

3.符号引用验证的目的是确定解析动作能正常执行,如果无法通过符号引用验证,那么将会抛出java.lang.IncompatibleClassChangeError异常的子类

三、准备

准备阶段是正式为类变量 分配内存并设置类变量初始值的阶段,这些变量所使用的内存将在方法区中进行分配。

四、解析

(1)解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

1.符号引用(symbolic Reference):符号引用逸一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用 时能无歧义地定位到引用目标即可。符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范中的class文件格式中。

2.直接引用(Direct Reference):直接引用可以是直接指向目标的指针。相对偏移量或是一个能间接定位到目标的句柄。直接引用是和虚拟机实现的内存布局相关的,同一个符号引用在不同的虚拟机实例上翻译出来的直接引用一般不会相同,如果有了直接引用那引用的目标必定已经在内存中存在。

(2)虚拟机规范中并未规定解析阶段发生的具体时间,只要求了执行anewarray,checkcast,getfield,getstatic,instanceof,invokedynamic,invokeinterface,invokespecial,invokestatic,invokevirtual,ldc,ldc_w,multianewarray,new,putField和putstatic这16个用于操作符号引用的字节码指令之前,先过它们所使用的符号引用进行解析。

(3)解析动作主要针对类或接口,字段,类方法,接口方法,方法类型,方法句柄和调用点限定符7类符号引用进行。

(4)类或接口的解析

虚拟机完成整个解析的过程需要以下3个步骤

1)如果c不是一个数组类型,那虚拟机将会把代表N的全限定名传递给D的类加载器去加载这个类C。在加载过程中,由于元数据验证,字节码验证的需要,又可能触发其他相关的类的加载动作。

2)如果C是一个数组类型,并且数组的元素类型为对象,那将会按以上的规则加载数组类型。如果N的描述符如前面所假设的形式,需要加载元素的类型,接着由虚拟机生成一个代表此数组维度和元素的数组对象。

3)如果上面的步骤没有出现任何异常,那么C在虚拟机中实际上已经成为一个有效的类或接口了,但在解析完成之后还要进行符号引用验证,确认D是否是具备对C的访问权限。

(5)字段解析

(6)类方法解析

(7)接口方法解析

五、初始化

1.类初始化阶段是类加载过程的最后一步

2.在准备阶段,变量已经赋过一次系统要过的初始值,而在初始化阶段,则根据程序员制定的主观去初始化变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器()方法的过程。

3.()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问。

4.()方法与类的构造函数不同,它不需要显式地调用父类构造器,虚拟机会保证在子类的()方法执行之前,父类的()方法已经执行完毕。因此在虚拟机中第一个被执行的()方法的类肯定有java.lang.object。

5.由父类的()方法先执行,也就意味着父类中定义的静态语句块要优先于子类的变量赋值操作。

6.()方法对于类或接口来说并不是必须的,如果一个类中没有静态语句块,也没有对变量的赋值操作,那么编译器可以不为这个类生成()方法

7.虚拟机会保证一个类的()方法在多个线程环境中正确地加锁,同步。

类加载器

一、类与类加载器

对于任意一个类,需要由加载它的加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。

二、双亲委派模型

(1)从Java虚拟机的角度来讲,只存在两种不同的类加载器:一种是启动类加载器(Bootstrap Class ClassLoader),这个类加载器使用C++语言实现是Java虚拟机自动的一部分;另一种就是所有其他的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,并且全都是继承自抽象类java.lang.classLoader.

(2)细分:启动类加载器(Bootstrap ClassLoader)

扩展类加载器(Extension ClassLoadert)

应用程序类加载器(Application ClassLoader)[系统类加载器]

(3)双亲委派模型工作过程:

如果一个类加载器收到了类加载器的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层类加载器中只有当父类加载器反馈自己无法完成这个类加载请求时,子类加载器才会尝试自己去加载。

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-04/129843.htm

linux

.NET跨平台实践:用C#开发Linux守护进程

JVM-字节码指令

相关资讯

JVM JVM类加载机制 JVM加载机制

JVM 运行时数据区域 (今 11:45)

JVM上的确定性执行机制 (05月12日)

JVM垃圾回收机制 (03月20日)

JVM类加载机制 (06月03日)

JVM虚拟机结构与机制 (04月17日)

JVM很重吗? (03月14日)

本文评论

查看全部评论 (0)

表情: 表情

姓名:

匿名

字数

同意评论声明

评论声明

尊重网上道德,遵守中华人民共和国的各项有关法律法规

承担一切因您的行为而直接或间接导致的民事或刑事法律责任

本站管理人员有权保留或删除其管辖留言中的任意内容

本站有权在网站内转载或引用您的评论

参与本评论即表明您已经阅读并接受上述条款

最新资讯

JVM 运行时数据区域

MySQL日志文件详述

MySQL一致性非锁定读和锁定读

Spark-2.2.0安装和部署详解

Scala-2.11.7安装笔记

配置SSH免密码登录

Hadoop 2.7.2集群搭建详解

Google发布Tensor2Tensor for TensorFlow

解决百度BMR的Spark集群开启slaves结点的问

Redhat 7.2 中文显示及中文输入法设置

背景:

阅读新闻

JVM-字节码指令

[日期:2016-04-05]

来源:Linux社区

作者:lrh-xl

[字体:大 中 小]

Java虚拟机字节码指令

了解了class文件,我觉得就很有必要去了解一下JVM中的字节码指令,那样堆class文件以及JVM运行机制也后很大的帮助.

Java虚拟机的指令由一个字节长度的,代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表所需参数(称为操作数,Oprands)而构成.由于Java虚拟机采用面向操作数栈而不是寄存器的架构,所以大多参数的指令都不包含操作数,只有一个操作码.

字节码指令的一些特性

由于限制了Java虚拟机操作码的长度为一个字节(0~255),这意味着指令集的操作码总数不可能超过256条.

由于class文件格式放弃了编译后的操作数长度对齐,这意味着虚拟机处理那些超过一个字节数据的时候,不得不在运行时从字节中重建出具体数据的结构.如果要将一个16位长度的无符号整数,使用两个无符号字节存储起来(将它们命名为byte1和byte2),那它们的值应该是这样的:(byte<<8)| byte2 .这种操作在某种程度上会导致解释执行字节码的时候会损失一些性能.但这样做的优势也是非常明显的,放弃了操作数长度对齐,就意味着可以省略很多填充和间隔符号:用一个字节来表示操作码,也是为了尽可能获得短小精干的编译代码.

字节码指令与数据类型

对于大部分与数据类型相关的字节码指令它们的操作码助记符中都有特殊特的字符来表明专门为哪种数据类型服务:i:代表int,l代表long,s代表short,b代表byte,c代表char,f代表float,d代表double,a代表reference.

Java虚拟机的指令集对于特定的操作只提供了有限的类型相关指令去支持它,换句话说,指令集将会故意被设计成非完全独立的Java虚拟机规范中把这种特性称为"Not Orthpogoal".即并非每种操作都有对应的指令.有一些单独的指令可以在必要的时候来将一些不支持的类型转换成为可被支持的类型.

加载和存储指令

加载和存储指令用于将数据在栈帧中的局部变量和操作数之间来回传输.

将一个局部变量加载到操作栈:ilaod , ioload,llaod , llaod,float,float,double,double,aload,aload.

将一个数据从操作数栈存储到局部变量表:istore,istore,lstore,lstore,fstore.fstore,dstore,dstore,astore,asotre.

将一个常量加载到数据栈:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_,lconst_,fconst_,dconst_

扩充局部变量表访问索引的指令:wide

运算指令

运算或算术指令用于对两个操作数栈上的值进行某种特定运算,并把结果重新存入到操作栈顶.

大体上算术指令可以分为两种:对整型数据进行运算的指令对浮点数据进行运算的指令.无论是哪种算术指令,都使用Java虚拟机的数据类型,由于没有直接支持byte,short,char和boolean类型的算术指令,对于这类数据的运算应使用操作int类型的指令代替.

加法指令:iadd,ladd,fadd,dadd

减法指令:isub,lsub,fsub,dsub

乘法指令:imul,lmul,fmul,dmul

求余指令:irem,lrem,frem,drem

求反指令:ineg,lneg,fneg,dneg

移位指令:ishl.ishr,lshl,lshr,lushr

按位或指令:ior,lor

按位与指令:iand,land]

按位异或指令:ixor,lxor

局部变量自增指令:iinc

比较指令:dcmpy,dcmpl,fcmpg,fsmpyl,lcomp

Java虚拟机要求在进行浮点数运算时,所有的运算结果都必须舍入到适当的精度,非精确的结果必须舍入为可被表示的最接近的精确值.如果有两种可表示的形式与该值一样接近,将优先选择最低有效位为零的,称为向最近数舍入模式.

在把浮点数转换为整数时,Java虚拟机使用IEEE754规范中的向零舍入模式,这中模式的舍入结果会导致数字被截断,所有小数部分的有效字节都会被丢弃掉.向零舍入模式将在目标数值类型与该数值类型中选择一个最接近但是不大于原数值的数字来作为最精确的舍入结果.

Java虚拟机在处理浮点数运算时,不会抛出任何运行时异常,当一个操作产生溢出时,将会使用有符号的无穷大来表示,如果某个操作结果没有明确的数学定义的话,将会使用NaN值来表示,所有使用NaN值作为操作数的算术运算,结果都会返回NaN.

在对long类型数值进行比较时,虚拟机采用带符号的比较方式,而对浮点数值,进行比较时(dcmpy,dcmpl,fcmpg,fcmpl),虚拟机会采用IEEE754规范所定义的无信号比较(Nonsignaling Conparions)方式.

类型转换指令

类型转换指令可以将两种不同的数值类型进行相互转换

Java直接支持(即转换时无需显示进行转换指令)以下数值类型的宽化类型转化(即范围类型向大范围类型的安全转化):

1.int -->long , float , double

2.long -->float , double

3.float -->double

处理窄化类型转换时,必须显示的使用转换指令来完成,这些转换指令包括:i2b , i2c , i2s , l2i , f2c , d2i , d2l , d2f.窄化类型转换可能会导致转换结果产生不同的正负号,不同的数量级的情况,转换可能会导致数值精度丢失.

将一个浮点型数值窄化为整型类型(int 或long)的时候,将遵循一下转换规则

?如果浮点值是NaN,那转换结果就是int或long类型的0.

?如果浮点值不是无穷大的话,浮点值使用向零舍入模式取整,获得整数v.如果v在目标类型的表示范围之内,转换结果就是v.

?否则,将根据v的符号,转换为一个T所能表示的最大会最小正数.

对象创建与访问指令

指令:

?创建类实例的指令:new

?创建数组得到指令:newarray , anewarray , multianewarray

?访问类字段(static 字段,或者称为类变量)和实例字段(非static 字段,或者称为实例变量)的指令:getfield , putfield , getstatic , putstatic\

?把一个数组元素加载到操作数栈的指令:baload , caload , saload , iaload , laload , faload , daload , aaload

?将一个操作数栈的值存储到数组元素中的指令:bastore , castore , sastore , iastore , fastore , dastore , aastore

?取数组长度的指令:arraylength

?检查类实例类型的指令:instanceof , checkcast

操作数栈管理指令

Java虚拟机提供了一些直接操作操作数的指令:

?操作数栈的栈顶一个或两个元素出栈:pop , po2

?复制栈顶一个或两个元素并将复制值或双份值重新压入栈顶:dup ,dup2,duo_x1,dup_x2,dup2_x2

?将栈最顶端的两个数值交换:swap

控制转移指令

控制转移指令可以让Java虚拟机有条件的从指定的位置而不是控制转移指令的下一条指令继续执行程序。可以认为控制转移指令就是在有条件或无条件的修改PC寄存器的值。

控制转移指令:

?条件分支:ifeq,iflt,ifne,ifge,ifgt,ifnull,ifnonnull,if_icmpeq,if_icmpne,if_icmplt,if_cmpgt,if_icmpge,if_cmpge,if_icmpeq,if_acmpne

?复合条件分支:tableswitch,lookupswitch

?无条件分支:goto,goto_w,jsr,jsr_w,ret

方法调用和返回指令

invokevirtual指令用于调用对象德邦实例方法,根据对象的实体的类型进行分派(虚方法分派),也就是Java语言中最常见的方法分派方式。

invokeinterface指令用于调用接口方法,它会在运行时搜索一个实现了这个接口方法的对象找出适合的方法进行调用。

invokespecial指令用于调用一些需要特殊处理的实例方法,包括实例初始化方法,私有方法和父类方法

involvestatic指令用于调用类的方法(static方法)

invokedynamic指令用于在运行时动态解析出调用点限定符所引用的方法,并执行该方法

前面4条调用指令的分派逻辑都固化在Java虚拟机的内部,而invokedynamic指令的分派逻辑是由用户设定的引导方法决定的

异常处理指令

在Java虚拟机中处理异常catch语句不是由字节码指令来实现的,而是用异常表来完成的。

在Java程序中显式抛出异常的操作(throw语句)都是由athrow来实现的,除了用throw语句显式抛出异常的情况之外,Java虚拟机规范还规定了许多运行时异常会在其他Java虚拟机指令检测到异常状况时自动抛出。

同步指令

Java虚拟机可以支持方法级的同步和方法内部一段指令序列的同步。这两种同步结构都是使用管理(Monitor)来支持的。

方法级的同步是隐含的,既无需通过字节码指令来控制,也实现在方法调用和返回操作之中。

同步一段指令序列通常是由Java语言中的synchronize语句块来表示的,Java虚拟机的指令集中有monitorenter和monitorexit两条指令来支持synchronize关键字的语义,正确实现synchronized关键字需要Java编译器与Java虚拟机两者共同协作支持

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-04/129844.htm

linux

JVM-类加载机制

获取C++类成员变量的地址偏移

相关资讯

JVM字节码 字节码指令

本文评论

查看全部评论 (0)

表情: 表情

姓名:

匿名

字数

同意评论声明

评论声明

尊重网上道德,遵守中华人民共和国的各项有关法律法规

承担一切因您的行为而直接或间接导致的民事或刑事法律责任

本站管理人员有权保留或删除其管辖留言中的任意内容

本站有权在网站内转载或引用您的评论

参与本评论即表明您已经阅读并接受上述条款

最新资讯

CentOS 6.4下双网卡bond配置

CentOS6.x双网卡采用主-备份策略绑定(bond

ORA-30036故障解决方法案例

ORA-03114: 未连接到 ORALCE 解决方法案例

Oracle RAC系统内存无法释放解决

Oracle Goldengate在HP平台裸设备文件系统

OGG升级运行ggsic报Unable to find library

Linux vi命令大全

VMware虚拟机主机模式下与主机互ping通

Linux内核中container_of函数详解

背景:

阅读新闻

获取C++类成员变量的地址偏移

[日期:2016-04-05]

来源:Linux社区

作者:openlib

[字体:大 中 小]

今天有在校学生问怎么获取类中的成员变量的地址偏移量,这个应该是很多初学C++的人很好奇的问题。以前我在学校的时候,也有过这种需求。忘了当时是要写什么“奇怪的程序”了,反正需要获取一个类的成员变量的地址偏移量。

其实这个问题很简单,如果你了解C++的类对象内存分布的话,这个根本不是问题。我给他举了个例子:

struct A

{

int i;

};

&((A*)0)->i; // 这样就可以获取到偏移量了。他表示不理解,OK,我们来具体说说。

假如定义个变量A a; 我们都知道 &a表示变量a的首地址,&(a.i)表示变量i的地址,那么&(a.i)减去&a不就得到i的偏移量了吗?

是的,就是这么简单。那么这个例子&((A*)0)->i;有什么关系呢?

&((A*)0)的地地址就是0,所以&((A*)0)->i 等于&((A*)0)->i减去0。

那个学生更好奇了,为什么&((A*)0)->i 不会出问题?这个例子里并没有为A的对象分配内存,那怎么可以得到它的地址呢?

是的,这里确实没有分配内存,但是这个例子里我们并没有要求有内存,我们也不对内存进行操作,所以不会引来崩溃。

&((A*)0)->i只是借助编译器为我们计算出它的地址。当编译器要用要一个成员变量的时候,它会根据对象的首地址加上成员的偏移量得到成员变量的地址。当对象的首地址为0时,得到的成员变量地址就是它的偏移量。

到这里,明白了吧!

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-04/129845.htm

linux

JVM-字节码指令

C语言中结构体的初始化

相关资讯

C++类 C++类成员变量

教你如何用C++创建一个特殊的类 (今 06:23)

C++类中虚表的详细讲解 (10/07/2016 08:15:54)

C++类的实例化对象的大小之sizeof( (02/05/2015 09:03:59)

C++空类实例大小不是0原因 (10/07/2016 08:27:55)

编写C++类的条款 (04/12/2015 09:43:44)

本文评论

查看全部评论 (0)

表情: 表情

姓名:

匿名

字数

同意评论声明

评论声明

尊重网上道德,遵守中华人民共和国的各项有关法律法规

承担一切因您的行为而直接或间接导致的民事或刑事法律责任

本站管理人员有权保留或删除其管辖留言中的任意内容

本站有权在网站内转载或引用您的评论

参与本评论即表明您已经阅读并接受上述条款

最新资讯

教你如何用C++创建一个特殊的类

Linux下的syslog日志守护进程深入理解

Adobe Creative Cloud本地安全限制绕过漏洞

众包组织暴力破解比特币钱包

CentOS 6.6 搭建Zabbix 3.0.3 过程

CentOS 6.5安装搭建Zabbix3.0详解PDF

MySQL同实例下复制表的2种方法

MySQL5.6的密码存放方式基础知识

C字符串相关知识总结

C malloc和calloc函数总结

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,293评论 18 399
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,568评论 25 707
  • 1.快捷键 门 dr 对齐 al 对齐AL 移动MV 偏移OF 复制CO#CC 镜像 - 拾取轴MM 旋转...
    流鱼青花阅读 499评论 0 0
  • 刘强东解决了马云一直以来担心的问题!京东物流以高效著称,很多用户早上下单,下午就能收到京东的快递,实在是让人瞠目结...
    数小码的科技阅读 560评论 0 0
  • 我一直和我的朋友们说,我很幸运,我父母的长辈都在,死亡对我来说很遥远,是一个出现在电视,小说中代表一个人不会再存在...
    陈晓蓓阅读 219评论 1 1