
QWS_MOUSE_PROTO=Tslib.1
用户启动文件
#bin/zhiyuan/input/etc/ts0
export
TSLIB_CALIBFILE=/:是“空格”+“&”符号)让其在后台运行.d/,若用户不需要启动QT,造成其他程序(比如Shell)无法通过串口终端与用户交互.conf
export
TSLIB_TSDEVICE=/inithome/etc/,则可能会导致位于其后的指令或程序无法得到执行ts/,那么设置hellow程序开机启动的方法如程序清单
1!/usrb/,可以直接删除
export
TSLIB_PLUGINDIR=/,you
can
delete
it
下面是启动QT界面的指令hellow
#start
qt
command.d/dev/,将要执行的指令添加到里面sh
#you
can
add
your
app
start_command
three
/home/。
程序清单1ts0
启动参数共分为三类;其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容;
其二是非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容;
其三是非Stable参数(-XX),此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用;
本文主要描述标准参数部分,剩下的两个部分将会陆续推出;
标准参数列表如下:
-client
设置jvm使用client模式,特点是启动速度比较快,但运行时性能和内存管理效率不高,通常用于客户端应用程序或者PC应用开发和调试。
-server
设置jvm使server模式,特点是启动速度比较慢,但运行时性能和内存管理效率很高,适用于生产环境。在具有64位能力的jdk环境下将默认启用该模式,而忽略-client参数。
-agentlib:libname[=options]
用于装载本地lib包;
其中libname为本地代理库文件名,默认搜索路径为环境变量PATH中的路径,options为传给本地库启动时的参数,多个参数之间用逗号分隔。 在Windows平台上jvm搜索本地库名为libname.dll的文件,在linux上jvm搜索本地库名为libname.so的文件,搜索路径环 境变量在不同系统上有所不同,比如Solaries上就默认搜索LD_LIBRARY_PATH。
比如:-agentlib:hprof
用来获取jvm的运行情况,包括CPU、内存、线程等的运行数据,并可输出到指定文件中;windows中搜索路径为JRE_HOME/bin/hprof.dll。
-agentpath:pathname[=options]
C/C++函数参数的传递方式有三种:值传递(pass by value)、指针传递(pass bypointer)、引用传递(pass by reference)。C/C++函数参数的传递通道是通过堆栈传递,默认遵循__cdecl(C声明方式),参数由调用者从右往左逐个压入堆栈,在函数调用完成之后再由调用者恢复堆栈。(Win32API遵循stdcall传参规范的,不在本文讨论范围)
下面是测试代码
void Swap(__int64* _pnX, __int64* _pnY)
{
__int64 nTemp = *_pnX
*_pnX = *_pnY
*_pnY = nTemp
}
void Swap(__int64&_nX, __int64&_nY)
{
__int64 nTemp = _nX
_nX = _nY
_nY = nTemp
}
void SetValue(__int64 _nX)
{
__int64 nTemp = _nX
}
// Test001
void GetMemory(__int64* _pBuff)
{
_pBuff = new __int64[4]
}
// Test002
void GetMemory(__int64** _ppBuff)
{
*_ppBuff = new __int64[4]
}
int _tmain(int argc, _TCHAR* argv[])
{
__int64 nA = 0x10
__int64 nB = 0x20
// Test to pass by pointer
Swap(&nA, &nB)
// Test to pass by reference
Swap(nA, nB)
// Test to pass by value
SetValue(nA)
// Test the pointer that points the pointer
__int64* _pArray = NULL
GetMemory(&_pArray)
delete[] _pArray
_pArray = NULL
// Test the pointer
GetMemory(_pArray)
return 0
}
指针传递和引用传递
// 下面看一下对应的反汇编的代码(VS版)
__int64 nA = 0x10
0041370E movdword ptr [nA],10h
movdword ptr [ebp-8],0
__int64 nB = 0x20
0041371C movdword ptr [nB],20h
movdword ptr [ebp-18h],0
// Test to pass by pointer
Swap(&nA, &nB)
0041372A leaeax,[nB]
0041372D pusheax
0041372E leaecx,[nA]
pushecx
callSwap (4111E5h)
addesp,8
// Test to pass by reference
Swap(nA, nB)
0041373A leaeax,[nB]
0041373D pusheax
0041373E leaecx,[nA]
pushecx
callSwap (4111E0h)
addesp,8
// GCC版
0x00401582 <+30>:leaeax,[esp+0x18]
0x00401586 <+34>:movDWORD PTR [esp+0x4],eax
0x0040158a <+38>:leaeax,[esp+0x1c]
0x0040158e <+42>:movDWORD PTR [esp],eax
0x00401591 <+45>:call 0x401520 <Swap(int*, int*)>
0x00401596 <+50>:leaeax,[esp+0x18]
0x0040159a <+54>:movDWORD PTR [esp+0x4],eax
0x0040159e <+58>:leaeax,[esp+0x1c]
0x004015a2 <+62>:movDWORD PTR [esp],eax
0x004015a5 <+65>:call 0x401542 <Swap(int&, int&)>
通过上面的反汇编代码,我们可以看出指针传递和引用传递在机制是一样的,都是将指针值(即地址)压入栈中,调用函数,然后恢复栈。Swap(nA, nB)和Swap(&nA, &nB)在实际上的汇编代码也基本上一模一样,都是从栈中取出地址来。由此可以看出引用和指针在效率上是一样的。这也是为什么指针和引用都可以达到多态的效果。指针传递和引用传递其实都是改变的地址指向的内存上的值来达到修改参数的效果。
值传递
下面是值传递对应的反汇编代码
// Test to pass by value
SetValue(nA)
0041374A moveax,dword ptr [ebp-8]
0041374D pusheax
0041374E movecx,dword ptr [nA]
00413751 pushecx
00413752 callSetValue (4111EAh)
00413757 addesp,8
因为我的机器是32位的CPU,从上面的汇编代码可以看64Bit的变量被分成2个32Bit的参数压入栈中。这也是我们常说的,值传递会形成一个拷贝。如果是一个自定义的结构类型,并且有很多参数,那么如果用值传递,这个结构体将被分割为非常多个32Bit的逐个拷贝到栈中去,这样的参数传递效率是非常慢的。所以结构体等自定义类型,都使用引用传递,如果不希望别人修改结构体变量,可以加上const修饰,如(const MY_STRUCT& _value)
下面来看一下Test001函数对应的反汇编代码的参数传递
__int64* _pArray = NULL
004137E0 movdword ptr [_pArray],0
// Test the pointer
GetMemory(_pArray)
moveax,dword ptr [_pArray]
pusheax
callGetMemory (411203h)
0041381B addesp,4
从上面的汇编代码可以看出,其实是0被压入到栈中作为参数,所以GetMemory(_pArray)无论做什么事,其实都与指针变量_pArray无关。GetMemory()分配的空间是让栈中的临时变量指向的,当函数退出时,栈得到恢复,结果申请的空间没有人管,就产生内存泄露的问题了。《C++ Primer》将参数传递分为引用传递和非引用传递两种,非引用传递其实可以理解为值传递。这样看来,指针传递在某种意义上也是值传递,因为传递的是指针的值(1个4BYTE的值)。值传递都不会改变传入实参的值的。而且普通的指针传递其实是改变的指针变量指向的内容。
下面再看一下Test002函数对应的反汇编代码的参数传递
__int64* _pArray = NULL
004137E0 movdword ptr [_pArray],0
GetMemory(&_pArray)
004137E7 leaeax,[_pArray]
004137EA pusheax
004137EB callGetMemory (4111FEh)
004137F0 addesp,4
从上面的汇编代码lea eax,[_pArray] 可以看出,_pArray的地址被压入到栈中去了。
然后看一看GetMemory(&_pArray)的实现汇编代码。
0x0040159b <+0>:push ebp
0x0040159c <+1>:movebp,esp
0x0040159e <+3>:subesp,0x18
0x004015a1 <+6>:movDWORD PTR [esp],0x20
0x004015a8 <+13>:call 0x473ef0 <_Znaj>
0x004015ad <+18>:movedx,DWORD PTR [ebp+0x8]
0x004015b0 <+21>:movDWORD PTR [edx],eax
0x004015b2 <+23>:leave
0x004015b3 <+24>:ret
蓝色的代码是分配临时变量空间,然后调用分配空间函数分配空间,得到的空间指针即eax.
然后红色的汇编代码即从ebp+0x8的栈上取到上面压入栈中的参数_pArray的地址.
mov DWORD PTR [edx],eax即相当于把分配的空间指针eax让edx指向,也即让_pArray指向分配的空间eax.
总之,无论是哪种参数传递方式,参数都是通过栈上的临时变量来间接参与到被调用函数的。指针作为参数,其本身的值是不可能被改变的,能够改变的是其指向的内容。引用是通过指针来实现的,所以引用和指针在效率上一样的。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)