??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲欧美一区二区三区久久,久久精品国产亚洲av麻豆小说
,久久中文字幕人妻熟av女 http://www.shnenglu.com/jianlinzhang/zh-cn Wed, 07 May 2025 18:25:15 GMT Wed, 07 May 2025 18:25:15 GMT 60 关于 boost ?VA 的一些见?/title> http://www.shnenglu.com/jianlinzhang/archive/2009/10/21/99091.html张徏?/dc:creator>张徏?/author>Wed, 21 Oct 2009 02:31:00 GMT http://www.shnenglu.com/jianlinzhang/archive/2009/10/21/99091.html http://www.shnenglu.com/jianlinzhang/comments/99091.html http://www.shnenglu.com/jianlinzhang/archive/2009/10/21/99091.html#Feedback 3 http://www.shnenglu.com/jianlinzhang/comments/commentRss/99091.html http://www.shnenglu.com/jianlinzhang/services/trackbacks/99091.html 今天Q我l于发现了其中的~由Q原来是因ؓ我的boost目录中包含的有中文字W串。。。哎Q没惛_啊。在重新讄了boost的目录后Q一切就ok了。。?br> 希望q对于有些同行来说有点用处。。。O(∩_∩)O哈哈~
]]> 堆和栈的区别 http://www.shnenglu.com/jianlinzhang/archive/2009/10/14/98545.html张徏?/dc:creator>张徏?/author>Wed, 14 Oct 2009 01:35:00 GMT http://www.shnenglu.com/jianlinzhang/archive/2009/10/14/98545.html http://www.shnenglu.com/jianlinzhang/comments/98545.html http://www.shnenglu.com/jianlinzhang/archive/2009/10/14/98545.html#Feedback 1 http://www.shnenglu.com/jianlinzhang/comments/commentRss/98545.html http://www.shnenglu.com/jianlinzhang/services/trackbacks/98545.html
1
堆和栈的区别 (转脓)
堆和栈的区别 (转脓) 非本Z?因非常经?所以收归旗?与众人阅?原作者不? 堆和栈的区别 一、预备知识—程序的内存分配 一个由c/C++~译的程序占用的内存分ؓ以下几个部分 1、栈区(stackQ?nbsp;q译器自动分配释放 Q存攑և数的参数|局部变量的值等。其操作方式cM于数据结构中的栈? 2、堆区(heapQ?nbsp;?nbsp;一般由E序员分配释放, 若程序员不释放,E序l束时可能由OS回收 。注意它与数据结构中的堆是两回事Q分配方式倒是cM于链表,呵呵? 3、全局区(静态区Q(staticQ—,全局变量和静态变量的存储是放在一块的Q初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在盔R的另一块区域?nbsp;- E序l束后有pȝ释放 4、文字常量区—常量字W串是攑֜q里的?nbsp;E序l束后由pȝ释放 5、程序代码区—存攑ևC的二q制代码? 二、例子程?nbsp; q是一个前辈写的,非常详细 //main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化?nbsp; main() { int b; ?nbsp; char s[] = "abc"; ?nbsp; char *p2; ?nbsp; char *p3 = "123456"; 123456\0在常量区Qp3在栈上?nbsp; static int c =0Q?nbsp;全局Q静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); 分配得来?0?0字节的区域就在堆区?nbsp; strcpy(p1, "123456"); 123456\0攑֜帔R区,~译器可能会它与p3所指向?123456"优化成一个地斏V?nbsp; } 二、堆和栈的理论知?nbsp; 2.1甌方式 stack: ql自动分配?nbsp;例如Q声明在函数中一个局部变?nbsp;int b; pȝ自动在栈中ؓb开辟空?nbsp; heap: 需要程序员自己甌Qƈ指明大小Q在c中malloc函数 如p1 = (char *)malloc(10); 在C++中用newq算W?nbsp; 如p2 = (char *)malloc(10); 但是注意p1、p2本n是在栈中的?nbsp; 2.2 甌后系l的响应 栈:只要栈的剩余I间大于所甌I间Q系l将为程序提供内存,否则报异常提示栈溢出?nbsp; 堆:首先应该知道操作pȝ有一个记录空闲内存地址的链表,当系l收到程序的甌Ӟ 会遍历该链表Q寻扄一个空间大于所甌I间的堆l点Q然后将该结点从I闲l点链表中删除,q将该结点的I间分配l程序,另外Q对于大多数pȝQ会在这块内存空间中的首地址处记录本ơ分配的大小Q这P代码中的delete语句才能正确的释放本内存I间。另外,׃扑ֈ的堆l点的大不一定正好等于申L大小Q系l会自动的将多余的那部分重新攑օI闲链表中?nbsp; 2.3甌大小的限?nbsp; 栈:在Windows?栈是向低地址扩展的数据结构,是一块连l的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是pȝ预先规定好的Q在WINDOWS下,栈的大小?MQ也有的说是1MQM是一个编译时q定的常数Q,如果甌的空间超q栈的剩余空间时Q将提示overflow。因此,能从栈获得的I间较小?nbsp; 堆:堆是向高地址扩展的数据结构,是不q箋的内存区域。这是由于系l是用链表来存储的空闲内存地址的,自然是不q箋的,而链表的遍历方向是由低地址向高地址。堆的大受限于计算机系l中有效的虚拟内存。由此可见,堆获得的I间比较灉|Q也比较大?nbsp; 2.4甌效率的比较: 栈由pȝ自动分配Q速度较快。但E序员是无法控制的?nbsp; 堆是由new分配的内存,一般速度比较慢,而且Ҏ产生内存片,不过用v来最方便. 另外Q在WINDOWS下,最好的方式是用VirtualAlloc分配内存Q他不是在堆Q也不是在栈是直接在q程的地址I间中保留一快内存,虽然用v来最不方ѝ但是速度快,也最灉|?nbsp; 2.5堆和栈中的存储内?nbsp; 栈: 在函数调用时Q第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句Q的地址Q然后是函数的各个参敎ͼ在大多数的C~译器中Q参数是由右往左入栈的Q然后是函数中的局部变量。注意静态变量是不入栈的?nbsp;
作者:121.30.67.*
2
堆和栈的区别 (转脓)
当本ơ函数调用结束后Q局部变量先出栈Q然后是参数Q最后栈指针指向最开始存的地址Q也是dC的下一条指令,E序p点l运行?nbsp; 堆:一般是在堆的头部用一个字节存攑֠的大。堆中的具体内容有程序员安排?nbsp; 2.6存取效率的比?nbsp; char s1[] = "aaaaaaaaaaaaaaa"; char *s2 = "bbbbbbbbbbbbbbbbb"; aaaaaaaaaaa是在q行时刻赋值的Q?nbsp; 而bbbbbbbbbbb是在~译时就定的; 但是Q在以后的存取中Q在栈上的数l比指针所指向的字W串(例如?快?nbsp; 比如Q?nbsp; #include void main() { char a = 1; char c[] = "1234567890"; char *p ="1234567890"; a = c[1]; a = p[1]; return; } 对应的汇~代?nbsp; 10: a = c[1]; 00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh] 0040106A 88 4D FC mov byte ptr [ebp-4],cl 11: a = p[1]; 0040106D 8B 55 EC mov edx,dword ptr [ebp-14h] 00401070 8A 42 01 mov al,byte ptr [edx+1] 00401073 88 45 FC mov byte ptr [ebp-4],al W一U在d时直接就把字W串中的元素d寄存器cl中,而第二种则要先把指针D到edx中,在根据edxd字符Q显然慢了?nbsp; 2.7结Q?nbsp; 堆和栈的区别可以用如下的比喻来看出: 使用栈就象我们去饭馆里吃饭,只管点菜Q发出申P、付钱、和吃(使用Q,吃饱了就赎ͼ不必理会切菜、洗菜等准备工作和洗、刷锅等扫尾工作Q他的好处是快捷Q但是自由度?nbsp; 使用堆就象是自己动手做喜Ƣ吃的菜_比较ȝQ但是比较符合自q口味Q而且自由度大?nbsp; windowsq程中的内存l构 在阅L文之前,如果你连堆栈是什么多不知道的话,请先阅读文章后面的基知识?nbsp; 接触q编E的人都知道Q高U语a都能通过变量名来讉K内存中的数据。那么这些变量在内存中是如何存放的呢Q程序又是如何用这些变量的呢?下面׃Ҏq行深入的讨论。下文中的C语言代码如没有特别声明,默认都用VC~译的release版?nbsp; 首先Q来了解一?nbsp;C 语言的变量是如何在内存分部的。C 语言有全局变量(Global)、本地变?Local)Q静态变?Static)、寄存器变量(Regeister)。每U变量都有不同的分配方式。先来看下面q段代码Q?nbsp; #include <stdio.h> int g1=0, g2=0, g3=0; int main() { static int s1=0, s2=0, s3=0; int v1=0, v2=0, v3=0; //打印出各个变量的内存地址 printf("0x%08x\n",&v1); //打印各本地变量的内存地址 printf("0x%08x\n",&v2); printf("0x%08x\n\n",&v3); printf("0x%08x\n",&g1); //打印各全局变量的内存地址 printf("0x%08x\n",&g2); printf("0x%08x\n\n",&g3); printf("0x%08x\n",&s1); //打印各静态变量的内存地址 printf("0x%08x\n",&s2); printf("0x%08x\n\n",&s3); return 0; } ~译后的执行l果是: 0x0012ff78 0x0012ff7c 0x0012ff80 0x004068d0 0x004068d4 0x004068d8 0x004068dc 0x004068e0 0x004068e4 输出的结果就是变量的内存地址。其中v1,v2,v3是本地变量,g1,g2,g3是全局变量Qs1,s2,s3是静态变量。你可以看到q些变量在内存是q箋分布的,但是本地变量和全局变量分配的内存地址差了十万八千里,而全局变量和静态变量分配的内存是连l的。这是因为本地变量和全局/静态变量是分配在不同类型的内存区域中的l果。对于一个进E的内存I间而言Q可以在逻辑上分?个部份:代码区,静态数据区和动态数据区。动态数据区一般就?#8220;堆栈”?#8220;?stack)”?#8220;?heap)”是两U不同的动态数据区Q栈是一U线性结构,堆是一U链式结构。进E的每个U程都有U有?#8220;?#8221;Q所以每个线E虽然代码一P但本地变量的数据都是互不q扰。一个堆栈可以通过“基地址”?#8220;栈顶”地址来描q。全局变量和静态变量分配在静态数据区Q本地变量分配在动态数据区Q即堆栈中。程序通过堆栈的基地址和偏U量来访问本地变量?nbsp;
作者:121.30.67.*
3
堆和栈的区别 (转脓)
├———————┤低端内存区域 ?nbsp;…… ?nbsp; ├———————┤ ?nbsp;动态数据区 ?nbsp; ├———————┤ ?nbsp;…… ?nbsp; ├———————┤ ?nbsp;代码?nbsp;?nbsp; ├———————┤ ?nbsp;静态数据区 ?nbsp; ├———————┤ ?nbsp;…… ?nbsp; ├———————┤高端内存区域 堆栈是一个先q后出的数据l构Q栈地址L于{于栈的基地址。我们可以先了解一下函数调用的q程Q以便对堆栈在程序中的作用有更深入的了解。不同的语言有不同的函数调用规定Q这些因素有参数的压入规则和堆栈的^衡。windows API的调用规则和ANSI C的函数调用规则是不一LQ前者由被调函数调整堆栈Q后者由调用者调整堆栈。两者通过“__stdcall”?#8220;__cdecl”前缀区分。先看下面这D代码: #include <stdio.h> void __stdcall func(int param1,int param2,int param3) { int var1=param1; int var2=param2; int var3=param3; printf("0x%08x\n",¶m1); //打印出各个变量的内存地址 printf("0x%08x\n",¶m2); printf("0x%08x\n\n",¶m3); printf("0x%08x\n",&var1); printf("0x%08x\n",&var2); printf("0x%08x\n\n",&var3); return; } int main() { func(1,2,3); return 0; } ~译后的执行l果是: 0x0012ff78 0x0012ff7c 0x0012ff80 0x0012ff68 0x0012ff6c 0x0012ff70 ├———————┤<—函数执行时的栈ӞESPQ、低端内存区?nbsp; ?nbsp;…… ?nbsp; ├———————┤ ?nbsp;var 1 ?nbsp; ├———————┤ ?nbsp;var 2 ?nbsp; ├———————┤ ?nbsp;var 3 ?nbsp; ├———————┤ ?nbsp;RET ?nbsp; ├———————┤<?#8220;__cdecl”函数q回后的栈顶QESPQ?nbsp; ?nbsp;parameter 1 ?nbsp; ├———————┤ ?nbsp;parameter 2 ?nbsp; ├———————┤ ?nbsp;parameter 3 ?nbsp; ├———————┤<?#8220;__stdcall”函数q回后的栈顶QESPQ?nbsp; ?nbsp;…… ?nbsp; ├———————┤<—栈底(基地址 EBPQ、高端内存区?nbsp; 上图是函数调用q程中堆栈的样子了。首先,三个参数以从又到左的ơ序压入堆栈Q先?#8220;param3”Q再?#8220;param2”Q最后压?#8220;param1”Q然后压入函数的q回地址(RET)Q接着跌{到函数地址接着执行Q这里要补充一点,介绍UNIX下的~冲溢出原理的文章中都提到在压入RET后,l箋压入当前EBPQ然后用当前ESP代替EBP。然而,有一介lwindows下函数调用的文章中说Q在windows下的函数调用也有q一步骤Q但Ҏ我的实际调试Qƈ未发现这一步,q还可以从param3和var1之间只有4字节的间隙这点看出来Q;W三步,栈?ESP)减去一个数Qؓ本地变量分配内存I间Q上例中是减?2字节(ESP=ESP-3*4Q每个int变量占用4个字?Q接着初始化本地变量的内存空间。由?#8220;__stdcall”调用p调函数调整堆栈,所以在函数q回前要恢复堆栈Q先回收本地变量占用的内?ESP=ESP+3*4)Q然后取回地址Q填入EIP寄存器,回收先前压入参数占用的内?ESP=ESP+3*4)Ql执行调用者的代码。参见下列汇~代码: ;--------------func 函数的汇~代?------------------ :00401000 83EC0C sub esp, 0000000C //创徏本地变量的内存空?nbsp; :00401003 8B442410 mov eax, dword ptr [esp+10] :00401007 8B4C2414 mov ecx, dword ptr [esp+14] :0040100B 8B542418 mov edx, dword ptr [esp+18] :0040100F 89442400 mov dword ptr [esp], eax :00401013 8D442410 lea eax, dword ptr [esp+10] :00401017 894C2404 mov dword ptr [esp+04], ecx ……………………Q省略若q代码) :00401075 83C43C add esp, 0000003C ;恢复堆栈Q回收本地变量的内存I间 :00401078 C3 ret 000C ;函数q回Q恢复参数占用的内存I间
作者:121.30.67.*
4
堆和栈的区别 (转脓)
;如果?#8220;__cdecl”的话Q这里是“ret”Q堆栈将p用者恢?nbsp; ;-------------------函数l束------------------------- ;--------------ȝ序调用func函数的代?------------- :00401080 6A03 push 00000003 //压入参数param3 :00401082 6A02 push 00000002 //压入参数param2 :00401084 6A01 push 00000001 //压入参数param1 :00401086 E875FFFFFF call 00401000 //调用func函数 ;如果?#8220;__cdecl”的话Q将在这里恢复堆栈,“add esp, 0000000C” 聪明的读者看到这里,差不多就明白~冲溢出的原理了。先来看下面的代码: #include <stdio.h> #include <string.h> void __stdcall func() { char lpBuff[8]="\0"; strcat(lpBuff,"AAAAAAAAAAA"); return; } int main() { func(); return 0; } ~译后执行一下回怎么P哈,“"0x00414141"指o引用?0x00000000"内存。该内存不能?read"?#8221;Q?#8220;非法操作”喽!"41"是"A"?6q制的ASCII码了Q那明显是strcatq句出的问题了?lpBuff"的大只?字节Q算q结\0Q那strcat最多只能写??A"Q但E序实际写入?1?A"外加1个\0。再来看看上面那q图Q多出来?个字节正好覆盖了RET的所在的内存I间Q导致函数返回到一个错误的内存地址Q执行了错误的指令。如果能_ֿ构造这个字W串Q它分成三部分Q前一部䆾仅仅是填充的无意义数据以辑ֈ溢出的目的,接着是一个覆盖RET的数据,紧接着是一DshellcodeQ那只要着个RET地址能指向这Dshellcode的第一个指令,那函数返回时p执行shellcode了。但是Y件的不同版本和不同的q行环境都可能媄响这Dshellcode在内存中的位|,那么要构造这个RET是十分困隄。一般都在RET和shellcode之间填充大量的NOP指oQ得exploit有更强的通用性?nbsp; ├———————┤<—低端内存区?nbsp; ?nbsp;…… ?nbsp; ├———————┤<—由exploit填入数据的开?nbsp; ?nbsp;?nbsp; ?nbsp;buffer ?lt;—填入无用的数据 ?nbsp;?nbsp; ├———————┤ ?nbsp;RET ?lt;—指向shellcodeQ或NOP指o的范?nbsp; ├———————┤ ?nbsp;NOP ?nbsp; ?nbsp;…… ?lt;—填入的NOP指oQ是RET可指向的范围 ?nbsp;NOP ?nbsp; ├———————┤ ?nbsp;?nbsp; ?nbsp;shellcode ?nbsp; ?nbsp;?nbsp; ├———————┤<—由exploit填入数据的结?nbsp; ?nbsp;…… ?nbsp; ├———————┤<—高端内存区?nbsp; windows下的动态数据除了可存放在栈中,q可以存攑֜堆中。了解C++的朋友都知道QC++可以使用new关键字来动态分配内存。来看下面的C++代码Q?nbsp; #include <stdio.h> #include <iostream.h> #include <windows.h> void func() { char *buffer=new char[128]; char bufflocal[128]; static char buffstatic[128]; printf("0x%08x\n",buffer); //打印堆中变量的内存地址 printf("0x%08x\n",bufflocal); //打印本地变量的内存地址 printf("0x%08x\n",buffstatic); //打印静态变量的内存地址 } void main() { func(); return; } E序执行l果为: 0x004107d0 0x0012ff04 0x004068c0 可以发现用new关键字分配的内存即不在栈中,也不在静态数据区。VC~译器是通过windows下的“?heap)”来实现new关键字的内存动态分配。在?#8220;?#8221;之前Q先来了解一下和“?#8221;有关的几个API函数Q?nbsp; HeapAlloc 在堆中申请内存空?nbsp; HeapCreate 创徏一个新的堆对象 HeapDestroy 销毁一个堆对象 HeapFree 释放甌的内?nbsp; HeapWalk 枚D堆对象的所有内存块 GetProcessHeap 取得q程的默认堆对象 GetProcessHeaps 取得q程所有的堆对?nbsp; LocalAlloc GlobalAlloc 当进E初始化Ӟpȝ会自动ؓq程创徏一个默认堆Q这个堆默认所占内存的大小?M。堆对象ql进行管理,它在内存中以铑ּl构存在。通过下面的代码可以通过堆动态申请内存空_
作者:121.30.67.*
5
堆和栈的区别 (转脓)
HANDLE hHeap=GetProcessHeap(); char *buff=HeapAlloc(hHeap,0,8); 其中hHeap是堆对象的句柄,buff是指向申L内存I间的地址。那q个hHeapI竟是什么呢Q它的值有什么意义吗Q看看下面这D代码吧Q?nbsp; #pragma comment(linker,"/entry:main") //定义E序的入?nbsp; #include <windows.h> _CRTIMP int (__cdecl *printf)(const char *, ...); //定义STL函数printf /*--------------------------------------------------------------------------- 写到q里Q我们顺便来复习一下前面所讲的知识Q?nbsp; (*?printf函数是C语言的标准函数库中函敎ͼVC的标准函数库由msvcrt.dll模块实现?nbsp; 由函数定义可见,printf的参C数是可变的,函数内部无法预先知道调用者压入的参数个数Q函数只能通过分析W一个参数字W串的格式来获得压入参数的信息,׃q里参数的个数是动态的Q所以必ȝ调用者来q堆栈Q这里便使用了__cdecl调用规则。BTWQWindowspȝ的API函数基本上是__stdcall调用形式Q只有一个API例外Q那是wsprintfQ它使用__cdecl调用规则Q同printf函数一Pq是׃它的参数个数是可变的~故?nbsp; ---------------------------------------------------------------------------*/ void main() { HANDLE hHeap=GetProcessHeap(); char *buff=HeapAlloc(hHeap,0,0x10); char *buff2=HeapAlloc(hHeap,0,0x10); HMODULE hMsvcrt=LoadLibrary("msvcrt.dll"); printf=(void *)GetProcAddress(hMsvcrt,"printf"); printf("0x%08x\n",hHeap); printf("0x%08x\n",buff); printf("0x%08x\n\n",buff2); } 执行l果为: 0x00130000 0x00133100 0x00133118 hHeap的值怎么和那个buff的值那么接q呢Q其实hHeapq个句柄是指向HEAP首部的地址。在q程的用户区存着一个叫PEB(q程环境?的结构,q个l构中存攄一些有兌E的重要信息Q其中在PEB首地址偏移0x18处存攄ProcessHeap是q程默认堆的地址Q而偏U?x90处存放了指向q程所有堆的地址列表的指针。windows有很多API都用进E的默认堆来存放动态数据,如windows 2000下的所有ANSI版本的函数都是在默认堆中甌内存来{换ANSI字符串到Unicode字符串的。对一个堆的访问是序q行的,同一时刻只能有一个线E访问堆中的数据Q当多个U程同时有访问要求时Q只能排队等待,q样侉K成E序执行效率下降?nbsp; 最后来说说内存中的数据寚w。所位数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍,DWORD数据的内存v始地址能被4除尽QWORD数据的内存v始地址能被2除尽Qx86 CPU能直接访问对齐的数据Q当他试图访问一个未寚w的数据时Q会在内部进行一pd的调_q些调整对于E序来说是透明的,但是会降低运行速度Q所以编译器在编译程序时会尽量保证数据对齐。同样一D代码,我们来看看用VC、Dev-C++和lcc三个不同~译器编译出来的E序的执行结果: #include <stdio.h> int main() { int a; char b; int c; printf("0x%08x\n",&a); printf("0x%08x\n",&b); printf("0x%08x\n",&c); return 0; } q是用VC~译后的执行l果Q?nbsp; 0x0012ff7c 0x0012ff7b 0x0012ff80 变量在内存中的顺序:b(1字节)-a(4字节)-c(4字节)?nbsp; q是用Dev-C++~译后的执行l果Q?nbsp; 0x0022ff7c 0x0022ff7b 0x0022ff74 变量在内存中的顺序:c(4字节)-中间盔R3字节-b(?字节)-a(4字节)?nbsp; q是用lcc~译后的执行l果Q?nbsp; 0x0012ff6c 0x0012ff6b 0x0012ff64 变量在内存中的顺序:同上?nbsp; 三个~译器都做到了数据对齐,但是后两个编译器昄没VC“聪明”Q让一个char占了4字节Q浪费内存哦?nbsp; 基础知识Q?nbsp; 堆栈是一U简单的数据l构Q是一U只允许在其一端进行插入或删除的线性表。允许插入或删除操作的一端称为栈Ӟ另一端称为栈底,对堆栈的插入和删除操作被UCؓ入栈和出栈。有一lCPU指o可以实现对进E的内存实现堆栈讉K。其中,POP指o实现出栈操作QPUSH指o实现入栈操作。CPU的ESP寄存器存攑ֽ前线E的栈顶指针QEBP寄存器中保存当前U程的栈底指针。CPU的EIP寄存器存放下一个CPU指o存放的内存地址Q当CPU执行完当前的指o后,从EIP寄存器中d下一条指令的内存地址Q然后l执行?nbsp;
作者:121.30.67.*
6
堆和栈的区别 (转脓)
参考:《Windows下的HEAP溢出及其利用》by: isno 《windows核心~程》by: Jeffrey Richter 摘要Q?nbsp;讨论常见的堆性能问题以及如何防范它们。(?nbsp;9 ) 前言 您是否是动态分配的 C/C++ 对象忠实且幸q的用户Q您是否在模块间的往q通信中频J地使用?#8220;自动?#8221;Q您的程序是否因堆分配而运行v来很慢?不仅仅您遇到q样的问题。几乎所有项目迟早都会遇到堆问题。大安惌Q?#8220;我的代码真正好,只是堆太?#8221;。那只是部分正确。更深入理解堆及其用法、以及会发生什么问题,是很有用的? 什么是堆? Q如果您已经知道什么是堆,可以跛_“什么是常见的堆性能问题Q?#8221;部分Q? 在程序中Q用堆来动态分配和释放对象。在下列情况下,调用堆操作: 事先不知道程序所需对象的数量和大小? 对象太大而不适合堆栈分配E序? 堆用了在运行时分配l代码和堆栈的内存之外的部分内存。下囄Z堆分配程序的不同层? GlobalAlloc/GlobalFreeQMicrosoft Win32 堆调用,q些调用直接与每个进E的默认堆进行对话? LocalAlloc/LocalFreeQWin32 堆调用(Z?nbsp;Microsoft Windows NT 兼容Q,q些调用直接与每个进E的默认堆进行对话? COM ?nbsp;IMalloc 分配E序Q或 CoTaskMemAlloc / CoTaskMemFreeQ:函数使用每个q程的默认堆。自动化E序使用“lg对象模型 (COM)”的分配程序,而申LE序使用每个q程堆? C/C++ q行?nbsp;(CRT) 分配E序Q提供了 malloc() ?nbsp;free() 以及 new ?nbsp;delete 操作W。如 Microsoft Visual Basic ?nbsp;Java {语a也提供了新的操作Wƈ使用垃圾攉来代替堆。CRT 创徏自己的私有堆Q驻留在 Win32 堆的剙? Windows NT 中,Win32 堆是 Windows NT q行时分配程序周围的薄层。所?nbsp;API 转发它们的请求给 NTDLL? Windows NT q行时分配程序提?nbsp;Windows NT 内的核心堆分配程序。它由具?nbsp;128 个大从 8 ?nbsp;1,024 字节的空闲列表的前端分配E序l成。后端分配程序用虚拟内存来保留和提交页? 在图表的底部?#8220;虚拟内存分配E序”Q操作系l用它来保留和提交c所有分配程序用虚拟内存进行数据的存取? 分配和释攑֝不就那么单吗Qؓ何花费这么长旉Q? 堆实现的注意事项 传统上,操作pȝ和运行时库是与堆的实现共存的。在一个进E的开始,操作pȝ创徏一个默认堆Q叫?#8220;q程?#8221;。如果没有其他堆可用,则块的分配?#8220;q程?#8221;。语aq行时也能在q程内创建单独的堆。(例如QC q行时创建它自己的堆。)除这些专用的堆外Q应用程序或许多已蝲入的动态链接库 (DLL) 之一可以创徏和用单独的堆。Win32 提供一整套 API 来创建和使用U有堆。有兛_函数Q英文)的详指|请参?nbsp;MSDN? 当应用程序或 DLL 创徏U有堆时Q这些堆存在于进E空_q且在进E内是可讉K的。从l定堆分配的数据在同一个堆上释放。(不能从一个堆分配而在另一个堆释放。) 在所有虚拟内存系l中Q堆ȝ在操作系l的“虚拟内存理?#8221;的顶部。语aq行时堆也驻留在虚拟内存剙。某些情况下Q这些堆是操作系l堆中的层,而语aq行时堆则通过大块的分配来执行自己的内存管理。不使用操作pȝ堆,而用虚拟内存函数更利于堆的分配和块的用? 典型的堆实现由前、后端分配程序组成。前端分配程序维持固定大块的空闲列表。对于一ơ分配调用,堆尝试从前端列表扑ֈ一个自由块。如果失败,堆被q从后端Q保留和提交虚拟内存Q分配一个大块来满h。通用的实现有每块分配的开销Q这耗费执行周期Q也减少了可使用的存储空间? Knowledge Base 文章 Q10758Q?#8220;?nbsp;calloc() ?nbsp;malloc() 理内存” Q搜索文章编P, 包含了有兌些主题的更多背景知识。另外,有关堆实现和设计的详l讨Z可在下列著作中找刎ͼ“Dynamic Storage Allocation: A Survey and Critical Review”Q作?nbsp;Paul R. Wilson、Mark S. Johnstone、Michael Neely ?nbsp;David BolesQ?#8220;International Workshop on Memory Management”, 作?nbsp;Kinross, Scotland, UK, 1995 q?nbsp;9 ?http://www.cs.utexas.edu/users/oops/papers.html) Q英文)?
作者:121.30.67.*
7
堆和栈的区别 (转脓)
Windows NT 的实玎ͼWindows NT 版本 4.0 和更新版本) 使用?nbsp;127 个大从 8 ?nbsp;1,024 字节?nbsp;8 字节寚w块空闲列表和一?#8220;大块”列表?#8220;大块”列表Q空闲列表[0]Q?nbsp;保存大于 1,024 字节的块。空闲列表容U了用双向链表链接在一L对象。默认情况下Q?#8220;q程?#8221;执行攉操作。(攉是将盔RI闲块合q成一个大块的操作。)攉耗费了额外的周期Q但减少了堆块的内部片? 单一全局锁保护堆Q防止多U程式的使用。(请参?#8220;Server Performance and Scalability Killers”中的W一个注意事? George Reilly 所著,?nbsp;“MSDN Online Web Workshop”上(站点Q?a target=_blank>http://msdn.microsoft.com/workshop/server/iis/tencom.asp Q英文)。)单一全局锁本质上是用来保护堆数据l构Q防止跨多线E的随机存取。若堆操作太频繁Q单一全局锁会Ҏ能有不利的影响? 什么是常见的堆性能问题Q? 以下是您使用堆时会遇到的最常见问题Q?nbsp; 分配操作造成的速度减慢。光分配p费很长旉。最可能Dq行速度减慢原因是空闲列表没有块Q所以运行时分配E序代码会耗费周期L较大的空闲块Q或从后端分配程序分配新块? 释放操作造成的速度减慢。释放操作耗费较多周期Q主要是启用了收集操作。收集期_每个释放操作“查找”它的盔R块,取出它们q构造成较大块,然后再把此较大块插入I闲列表。在查找期间Q内存可能会随机到Q从而导致高速缓存不能命中,性能降低? 堆竞争造成的速度减慢。当两个或多个线E同时访问数据,而且一个线El进行之前必ȝ待另一个线E完成时发生竞争。竞争LDȝQ这也是目前多处理器pȝ遇到的最大问题。当大量使用内存块的应用E序?nbsp;DLL 以多U程方式q行Q或q行于多处理器系l上Q时导致速度减慢。单一锁定的用—常用的解决Ҏ—意味着使用堆的所有操作是序列化的。当{待锁定时序列化会引LE切换上下文。可以想象交叉\口闪烁的U灯处走走停停导致的速度减慢?nbsp; 竞争通常会导致线E和q程的上下文切换。上下文切换的开销是很大的Q但开销更大的是数据从处理器高速缓存中丢失Q以及后来线E复zL的数据重建? 堆破坏造成的速度减慢。造成堆破坏的原因是应用程序对堆块的不正确使用。通常情Ş包括释放已释攄堆块或用已释放的堆块,以及块的界重写{明N题。(破坏不在本文讨论范围之内。有兛_存重写和泄漏{其他细节,请参?nbsp;Microsoft Visual C++(R) 调试文 。) 频繁的分配和重分配造成的速度减慢。这是用脚本语a旉常普遍的现象。如字符串被反复分配Q随重分配增长和释放。不要这样做Q如果可能,量分配大字W串和用缓冲区。另一U方法就是尽量少用连接操作? 竞争是在分配和释放操作中D速度减慢的问题。理x况下Q希望用没有竞争和快速分?释放的堆。可惜,现在q没有这L通用堆,也许来会有? 在所有的服务器系l中Q如 IIS、MSProxy、DatabaseStacks、网l服务器?nbsp;Exchange 和其他), 堆锁定实在是个大瓉。处理器数越多,竞争p会恶化? 量减少堆的使用 现在您明白用堆时存在的问题了,N您不x有能解决q些问题的超U魔吗Q我可希望有。但没有法能堆运行加快—因此不要期望在产品之前的最后一星期能够大ؓ改观。如果提前规划堆{略Q情况将会大大好转。调整用堆的方法,减少对堆的操作是提高性能的良斏V? 如何减少使用堆操作?通过利用数据l构内的位置可减堆操作的次数。请考虑下列实例Q? struct ObjectA { // objectA 的数?nbsp; } struct ObjectB { // objectB 的数?nbsp; } // 同时使用 objectA ?nbsp;objectB // // 使用指针 // struct ObjectB { struct ObjectA * pObjA; // objectB 的数?nbsp; } // // 使用嵌入
作者:121.30.67.*
8
堆和栈的区别 (转脓)
// struct ObjectB { struct ObjectA pObjA; // objectB 的数?nbsp; } // // 集合 – 在另一对象内?nbsp;objectA ?nbsp;objectB // struct ObjectX { struct ObjectA objA; struct ObjectB objB; } 避免使用指针兌两个数据l构。如果用指针关联两个数据结构,前面实例中的对象 A ?nbsp;B 被分别分配和释放。这会增加额外开销—我们要避免q种做法? 把带指针的子对象嵌入父对象。当对象中有指针Ӟ则意味着对象中有动态元素(癑ֈ之八十)和没有引用的C|。嵌入增加了位置从而减了q一步分?释放的需求。这提高应用程序的性能? 合ƈ对象Ş成大对象Q聚合)。聚合减分配和释放的块的数量。如果有几个开发者,各自开发设计的不同部分Q则最l会有许多小对象需要合q。集成的挑战是要找到正的聚合边界? 内联~冲够满百分之八十的需要(aka 80-20 规则Q。个别情况下Q需要内存缓冲区来保存字W串/二进制数据,但事先不知道d节数。估计ƈ内联一个大能满癑ֈ之八十需要的~冲区。对剩余的百分之二十Q可以分配一个新的缓冲区和指向这个缓冲区的指针。这P减分配和释放调用q增加数据的位置I间Q从Ҏ上提高代码的性能? 在块中分配对象(块化Q。块化是以组的方式一ơ分配多个对象的Ҏ。如果对列表的项q箋跟踪Q例如对一?nbsp;{名称Q值} 对的列表Q有两种选择Q选择一是ؓ每一?#8220;名称-?#8221;对分配一个节点;选择二是分配一个能容纳Q如五个Q?#8220;名称-?#8221;对的l构。例如,一般情况下Q如果存储四对,可减少节点的数量,如果需要额外的I间数量Q则使用附加的链表指针?nbsp; 块化是友好的处理器高速缓存,特别是对?nbsp;L1-高速缓存,因ؓ它提供了增加的位|?nbsp;—不用说对于块分配,很多数据块会在同一个虚拟页中? 正确使用 _amblksiz。C q行?nbsp;(CRT) 有它的自定义前端分配E序Q该分配E序从后端(Win32 堆)分配大小?nbsp;_amblksiz 的块。将 _amblksiz 讄高的D潜在地减对后端的调用次数。这只对q泛使用 CRT 的程序适用? 使用上述技术将获得的好处会因对象类型、大及工作量而有所不同。但总能在性能和可升羃性方面有所收获。另一斚wQ代码会有点ҎQ但如果l过深思熟虑,代码q是很容易管理的? 其他提高性能的技? 下面是一些提高速度的技术: 使用 Windows NT5 ?nbsp; ׃几个同事的努力和辛勤工作Q?998 q初 Microsoft Windows(R) 2000 中有了几个重大改q: 改进了堆代码内的锁定。堆代码Ҏ堆一个锁。全局锁保护堆数据l构Q防止多U程式的使用。但不幸的是Q在高通信量的情况下,堆仍受困于全局锁,D高竞争和低性能。Windows 2000 中,锁内代码的界区竞争的可能性减到最?从而提高了可~性? 使用 “Lookaside”列表。堆数据l构对块的所有空闲项使用了大在 8 ?nbsp;1,024 字节Q以 8-字节递增Q的快速高速缓存。快速高速缓存最初保护在全局锁内。现在,使用 lookaside 列表来访问这些快速高速缓存空闲列表。这些列表不要求锁定Q而是使用 64 位的互锁操作Q因此提高了性能? 内部数据l构法也得到改q? q些改进避免了对分配高速缓存的需求,但不排除其他的优化。?nbsp;Windows NT5 堆评估您的代码;它对于 1,024 字节 (1 KB) 的块Q来自前端分配程序的块)是最佳的。GlobalAlloc() ?nbsp;LocalAlloc() 建立在同一堆上Q是存取每个q程堆的通用机制。如果希望获得高的局部性能Q则使用 Heap(R) API 来存取每个进E堆Q或为分配操作创q堆。如果需要对大块操作Q也可以直接使用 VirtualAlloc() / VirtualFree() 操作? 上述改进已在 Windows 2000 beta 2 ?nbsp;Windows NT 4.0 SP4 中用。改q后Q堆锁的竞争率显著降低。这使所?nbsp;Win32 堆的直接用户受益。CRT 堆徏立于 Win32 堆的剙Q但它用自q块堆,因而不能从 Windows NT 改进中受益。(Visual C++ 版本 6.0 也有改进的堆分配E序。)
作者:121.30.67.*
9
堆和栈的区别 (转脓)
使用分配高速缓?nbsp; 分配高速缓存允讔R速缓存分配的块,以便来重用。这能够减少对进E堆Q或全局堆)的分?释放调用的次敎ͼ也允许最大限度的重用曄分配的块。另外,分配高速缓存允许收集统计信?以便较好地理解对象在较高层次上的使用? 典型圎ͼ自定义堆分配E序在进E堆的顶部实现。自定义堆分配程序与pȝ堆的行ؓ很相伹{主要的差别是它在进E堆的顶部ؓ分配的对象提供高速缓存。高速缓存设计成一套固定大(?nbsp;32 字节?4 字节?28 字节{)。这一个很好的{略Q但q种自定义堆分配E序丢失与分配和释放的对象相关的“语义信息”?nbsp; 与自定义堆分配程序相反,“分配高速缓?#8221;作ؓ每类分配高速缓存来实现。除能够提供自定义堆分配E序的所有好处之外,它们q能够保留大量语义信息。每个分配高速缓存处理程序与一个目标二q制对象兌。它能够使用一套参数进行初始化Q这些参数表Cƈ发别、对象大和保持在空闲列表中的元素的数量{。分配高速缓存处理程序对象维持自qU有I闲实体池(不超q指定的阀|q用私有保护锁。合在一P分配高速缓存和U有锁减了与主pȝ堆的通信量,因而提供了增加的ƈ发、最大限度的重用和较高的可~性? 需要用清理程序来定期查所有分配高速缓存处理程序的zd情况q回收未用的资源。如果发现没有活动,释攑ֈ配对象的池,从而提高性能? 可以审核每个分配/释放zd。第一U信息包括对象、分配和释放调用的L。通过查看它们的统计信息可以得出各个对象之间的语义关系。利用以上介l的许多技术之一Q这U关pd以用来减内存分配? 分配高速缓存也起到了调试助手的作用Q帮助您跟踪没有完全清除的对象数量。通过查看动态堆栈返回踪q和除没有清除的对象之外的签名,甚至能够扑ֈ切的失败的调用者? MP ?nbsp; MP 堆是对多处理器友好的分布式分配的E序包,?nbsp;Win32 SDKQWindows NT 4.0 和更新版本)中可以得到。最初由 JVert 实现Q此处堆抽象建立?nbsp;Win32 堆程序包的顶部。MP 堆创建多?nbsp;Win32 堆,q试囑ְ分配调用分布C同堆Q以减少在所有单一锁上的竞争? 本程序包是好的步?nbsp;—一U改q的 MP-友好的自定义堆分配程序。但是,它不提供语义信息和缺乏统计功能。通常?nbsp;MP 堆作?nbsp;SDK 库来使用。如果用这?nbsp;SDK 创徏可重用组Ӟ您将大大受益。但是,如果在每?nbsp;DLL 中徏立这?nbsp;SDK 库,增加工作设|? 重新思考算法和数据l构 要在多处理器机器上~,则算法、实现、数据结构和g必须动态~。请看最l常分配和释攄数据l构。试问,“我能用不同的数据l构完成此工作吗Q?#8221;例如Q如果在应用E序初始化时加蝲了只读项的列表,q个列表不必是线性链接的列表。如果是动态分配的数组非常好。动态分配的数组减内存中的堆块和片Q从而增强性能? 减少需要的对象的数量减少堆分配程序的负蝲。例如,我们在服务器的关键处理\径上使用五个不同的对象,每个对象单独分配和释放。一起高速缓存这些对象,把堆调用从五个减到一个,显著减少了堆的负载,特别当每U钟处理 1,000 个以上的h时? 如果大量使用“Automation”l构Q请考虑从主U代码中删除“Automation BSTR”Q或臛_避免重复?nbsp;BSTR 操作。(BSTR q接Dq多的重分配和分?释放操作。) 摘要 Ҏ有^台往往都存在堆实现Q因此有巨大的开销。每个单独代码都有特定的要求Q但设计能采用本文讨论的基本理论来减堆之间的相互作用?nbsp; 评h您的代码中堆的用? 改进您的代码Q以使用较少的堆调用Q分析关键\径和固定数据l构? 在实现自定义的包装程序之前用量化堆调用成本的方法? 如果Ҏ能不满意,误?nbsp;OS l改q堆。更多这c请求意味着Ҏq堆的更多关注? 要求 C q行时组针对 OS 所提供的堆制作y的分配包装程序。随着 OS 堆的改进QC q行时堆调用的成本将减小? 操作pȝQWindows NT 家族Q正在不断改q堆。请随时x和利用这些改q? Murali Krishnan ?nbsp;Internet Information Server (IIS) l的首席软g设计工程师。从 1.0 版本开始他p?nbsp;IISQƈ成功发行?nbsp;1.0 版本?nbsp;4.0 版本。Murali l织q?nbsp;IIS 性能l三q?nbsp;(1995-1998), 从一开始就影响 IIS 性能。他拥有威斯h?nbsp;Madison 大学?nbsp;M.S.和印?nbsp;Anna 大学?nbsp;B.S.。工作之外,他喜Ƣ阅诅R打排球和家庭烹饪?
原帖来自于:http://tieba.baidu.com/f?kz=150791801
]]> I/O 同步Q异步,dQ非d问题 http://www.shnenglu.com/jianlinzhang/archive/2009/07/10/89739.html张徏?/dc:creator>张徏?/author>Fri, 10 Jul 2009 09:30:00 GMT http://www.shnenglu.com/jianlinzhang/archive/2009/07/10/89739.html http://www.shnenglu.com/jianlinzhang/comments/89739.html http://www.shnenglu.com/jianlinzhang/archive/2009/07/10/89739.html#Feedback 0 http://www.shnenglu.com/jianlinzhang/comments/commentRss/89739.html http://www.shnenglu.com/jianlinzhang/services/trackbacks/89739.html IO - 同步Q异步,dQ非d 同步QsynchronousQ?IO和异步(asynchronousQ?IOQ阻塞(blockingQ?IO和非dQnon-blockingQIO Q我怿q几个词困扰q很多hQ更痛苦的是Q如果你查阅q文献资料,你会发现不同的资料中的解释是不一LQ例如在wiki中,异步和非d被当成了一个概??br>出现q种情况的原因,我认为很大程度上是因为IOq个概念本n很宽泛Q它其实包含了好几个层面。比如说Q你可以把它看做是一个物理上的设备,也可以看做是 OS抽象出来的一个YӞq可以看做是qx写程序用的read(),write()函数Q不同的层面对于q几个词的理解也是不一L?/p>
先看一个较低的层次。如果从CPU的角度看Q其实大部分的IO都是异步的:因ؓCPU启动q个IO操作后,去q其它的事情了,一直到产生一个中断,告诉它IO完成了?br>“Most physical I/O is asynchronous—the CPU starts the transfer and goes off to do something else until the interrupt arrives. User programs are much easier to write if the I/O operations are blocking—after a read system call the program is automatically suspended until the data are available in the buffer. It is up to the operating system to make operations that are actually interrupt-driven look blocking to the user programs.” Q引?Modern Operating Systems, 2edQ?/p>
不过Q本文ƈ不想探究那么底层的东东。作为程序员Q更多的q是从应用层面来考虑。所以,以下重点介绍的是应用E序中能够采用的四种IO机制?br>Q说明,下文中图片引用自 http://www.ibm.com/developerworks/cn/linux/l-async/ Q?/p>
首先Q从最常用到的Q也是最Ҏ理解的同步阻塞IO 说v?/p>
在这个模型中Q应用程序(applicationQؓ了执行这个read操作Q会调用相应的一个system callQ将pȝ控制权交lkernelQ然后就q行{待Q这其实是被阻塞了Q。kernel开始执行这个system callQ执行完毕后会向应用E序q回响应Q应用程序得到响应后Q就不再dQƈq行后面的工作?br>
例如Q?#8220;在调?read pȝ调用Ӟ应用E序会阻塞ƈ对内核进行上下文切换。然后会触发L作,当响应返回时Q从我们正在从中d的设备中q回Q,数据pUd到用L间的~冲Z。然后应用程序就会解除阻塞(read 调用q回Q?#8221;
举一个浅昄例子Q就好比你去一个银行柜台存钱。首先,你会存q单子填好Q然后交l柜员。这里,你就好比是applicationQ单子就是调用的 system callQ柜员就是kernel。提交好单子后,你就坐在柜台前等Q相当于开始进行等待。柜员办好以后会l你一个回执,表示办好了,q就?response。然后你可以拿着回执q其它的事了。注意,q个时候,如果你办完之后马上去查̎Q存的钱已经打到你的账户上了。后面你会发玎ͼq点很重要?/p>
接下来谈同步非阻塞IO ?br>先看q个图,
在linux下,应用E序可以通过讄文g描述W的属性O_NONBLOCKQI/O操作可以立即q回Q但是ƈ不保证I/O操作成功?br>也就是说Q当应用E序讄了O_NONBLOCK之后Q执行write操作Q调用相应的system callQ这个system call会从内核中立卌回。但是在q个q回的时间点Q数据可能还没有被真正的写入到指定的地方。也是_kernel只是很快的返回了q个 system callQ这P应用E序不会被这个IO操作blockingQ,但是q个system call具体要执行的事情Q写数据Q可能ƈ没有完成。而对于应用程序,虽然q个IO操作很快p回了Q但是它q不知道q个IO操作是否真的成功了,如果想知道,需要应用程序主动地去问kernel?/p>
q次不是去银行存钱,而是去银行汇ƾ。同LQ你也需要填写汇Ƒ֍然后交给柜员Q柜员进行一些简单的手箋处理p够给你回执。但是,你拿到回执ƈ不意味着钱已l打CҎ的̎上。事实上Q一般汇Ƅ周期大概?4个小Ӟ如果你要以存q模式来汇Ƅ话,意味着你需要在银行{?4个小Ӟq显然是不现实的。所以,同步非阻塞IO在实际生zM也是有它的意义的?/p>
再来谈谈异步dIO ?br>在linux中,常常通过select/poll来实现这U机制?/p>
以图ZQ?br>和之前一P应用E序要执行read操作Q因此调用一个system callQ这个system call被传递给了kernel。但在应用程序这边,它调用system call之后Qƈ不等待kernelq回responseQ这一Ҏ和前面两U机制不一L地方。这也是Z么它被称为异步的原因。但是ؓ什么称其ؓd呢?q是因ؓ虽然应用E序是一个异步的方式Q但是select()函数会将应用E序d住,一直等到这个system call有结果返回了Q再通知应用E序。也是_“在这U模型中Q配|的是非d I/OQ然后用阻?select pȝ调用来确定一?I/O 描述W何时有操作?#8221; 所以,从IO操作的实际效果来看,异步dIO和第一U同步阻塞IO是一LQ应用程序都是一直等到IO操作成功之后Q数据已l被写入或者读取)Q才开始进行下面的工作。异步阻塞IO的好处在于一个select函数可以为多个描q符提供通知Q提高了q发性?/p>
关于提高q发性这点,我们q以银行Z说明。比如说一个银行柜収ͼ现在?0个h惛_钱。按照现在银行的做法Q一个个排队。第一个h先填存款单,然后提交Q然后柜员处理,然后l回执,成功后再轮到下一个h。大家应该都在银行排q对Q这L程是很痛苦的。如果按照异步阻塞的机制Q?0个h都填好存Ƒ֍Q然后都提交l柜収ͼ提交完之后所有的10个h在银行大厅{待。这时候会专门有个人,他会了解存款单处理的情况Q一旦有存款单处理完毕,他会回执交l相应的正在大厅{待的hQ这个拿到回执的人就可以d其他的事情了。而前面提到的q个专hQ就对应于select函数?/p>
最后,谈谈异步非阻塞IO ?br>q个概念相对前面两个反而更Ҏ理解一些?/p>
如图所C,应用E序提交readh的system callQ然后,kernel开始处理相应的IO操作Q而同Ӟ应用E序q不{kernelq回响应Q就会开始执行其他的处理操作Q应用程序没有被IO操作所dQ。当kernel执行完毕Q返回read的响应,׃产生一个信h执行一个基于线E的回调函数来完成这?I/O 处理q程?/p>
比如银行存钱。现在某银行新开通了一存׃务。用户之需要将存款单交l柜収ͼ然后无需{待可以离开了。柜台办好以后会l用户发送一条短信,告知交易成功。这L户不需要在柜台前进行长旉的等待,同时Q也能够得到切的消息知道交易完成?/p>
从前面的介绍中可以看出,所谓的同步和异步,在这里指的是application和kernel之间的交互方式。如果application不需要等?kernel的回应,那么它就是异步的。如果application提交完IOh后,需要等?#8220;回执”Q那么它是同步的?br>而阻塞和非阻塞,指的是application是否{待IO操作的完成。如果application必须{到IO操作实际完成以后再执行下面的操作Q那么它是阻塞的。反之,如果不等待IO操作的完成就开始执行其它操作,那么它是非阻塞的?/p>
本文来自CSDN博客Q{载请标明出处Q?a >http://blog.csdn.net/historyasamirror/archive/2009/06/15/4270633.aspx
]]> 使用CString的方?/title> http://www.shnenglu.com/jianlinzhang/archive/2009/07/02/89047.html张徏?/dc:creator>张徏?/author>Thu, 02 Jul 2009 02:58:00 GMT http://www.shnenglu.com/jianlinzhang/archive/2009/07/02/89047.html http://www.shnenglu.com/jianlinzhang/comments/89047.html http://www.shnenglu.com/jianlinzhang/archive/2009/07/02/89047.html#Feedback 0 http://www.shnenglu.com/jianlinzhang/comments/commentRss/89047.html http://www.shnenglu.com/jianlinzhang/services/trackbacks/89047.html #include <string> using namespace std; 但肯定不如CString功能强大Q其实在非MFCE序中用CStringQ也是可以的Q具体方法如下: Z使用CStringc,首先源文件必L以cppl尾的,q是因ؓvc默认对不同的扩展名采用不同的~译Ҏ和错误检查,mfc的支持文件Afx.h只有由cpp为扩展名的文件包含才能够正常~译。对于exe和库要采用不同的方式。下面分别讨论: 一、在非dll或者lib的工E里Q用CString非常ҎQ只要两步: 1、对于没有包?lt;Windows.h>的stdafx.h中,只要包含了afx.h卛_Q而对于已l包含了<windows.h>的stdafx.h, 一定需要保证afx.h在windows.h之前被包含。另外由于默认的控制台程序采用的单线E运行库Q我们要把它Ҏ多线E库Q这些工作只要在stdafx.h中进行修改就可以了(详细信息可以参考候捷?lt;<mfc 深入出>>Q,我用的一个stdafx.h的例子如下(q是一个从向导生成的win32位GUI的程序的stdafx.h修改的)Q?br> // stdafx。h #if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) #define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include <afx.h> // 加在q里 // Windows Header Files: #include <windows.h> // C RunTime Header Files #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <tchar.h> #ifdef _DEBUG #pragma comment(lib, "libcmtd.lib") #else #pragma comment(lib, "libcmt.lib") #endif // Local Header Files #endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) q样可以在E序中正怋用CStringcM?br> 二、在dll或者lib的工E中Q由于afx.h默认带了一个DllMainQ致使要使用CStringc需要几个步骤?br> 1、首先和控制台程序一P如果~译环境讄了采用单U程? 要改成多U程库,q个可以从工E属性里q行修改Q详l信息可以参考候捷?lt;<mfc 深入出>>. 下面l出的是我常用的方式Q可以直接把它复制到工程里用: #ifdef _DEBUG #pragma comment(lib, "libcmtd.lib") #else #pragma comment(lib, "libcmt.lib") #endif 2、工E目录下创徏一个DLLMODUL.CPP文gQƈ且把它加入到当前工程中?br> 3、打开DLLMODUL.CPP文gQ编辑这个文件ؓq样Q?br> #include "stdafx.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW ///////////////////////////////////////////////////////////////////////////// // global data // The following symbol used to force inclusion of this module for _USRDLL #ifdef _X86_ extern "C" { int _afxForceUSRDLL; } #else extern "C" { int __afxForceUSRDLL; } #endif 4、打开stdafx.hQ把afx.h包含在windows.h前面。现在可以正常的使用CString了?
]]> 关于 vs2005 dcL者变?出错问题的解x?/title> http://www.shnenglu.com/jianlinzhang/archive/2009/05/26/85768.html张徏?/dc:creator>张徏?/author>Tue, 26 May 2009 02:11:00 GMT http://www.shnenglu.com/jianlinzhang/archive/2009/05/26/85768.html http://www.shnenglu.com/jianlinzhang/comments/85768.html http://www.shnenglu.com/jianlinzhang/archive/2009/05/26/85768.html#Feedback 3 http://www.shnenglu.com/jianlinzhang/comments/commentRss/85768.html http://www.shnenglu.com/jianlinzhang/services/trackbacks/85768.html 该解x案如下: Q?Q下载vs2005 补丁,下蝲链接为:Microsoft Visual C++ 2005 SP1 Redistributable Package (x86) Q安装之。。?br>Q?Q下载需要修Ҏ册表的一个工E?下蝲地址为:http://download.csdn.net/source/1145363 Q运行之。。?br>xQ问题就已解冻I 当然引v该问题的主要原因是由于IE8的用,如果你觉得以上方法比较复杂,可直接卸载掉IE8.。。?br> 在此Q我要感?a >http://jiangsheng.spaces.live.com/blog/cns!1BE894DEAF296E0A!878.entry 文章的博丅R。。?
]]> socket 同步 异步 d 非阻?/title> http://www.shnenglu.com/jianlinzhang/archive/2009/05/18/83297.html张徏?/dc:creator>张徏?/author>Mon, 18 May 2009 09:36:00 GMT http://www.shnenglu.com/jianlinzhang/archive/2009/05/18/83297.html http://www.shnenglu.com/jianlinzhang/comments/83297.html http://www.shnenglu.com/jianlinzhang/archive/2009/05/18/83297.html#Feedback 0 http://www.shnenglu.com/jianlinzhang/comments/commentRss/83297.html http://www.shnenglu.com/jianlinzhang/services/trackbacks/83297.html 同步Q函数没有执行完不返回,U程被挂?
dQ没有收完数据函Cq回Q线E也被挂?/p>
异步Q函数立卌回,通过事g或是信号通知调用?/p>
非阻塞:函数立即q回Q通过select通知调用?/p>
q样看来异步和非d有什么区别呢Q?/p>
异步=非阻塞?
同步是在操作pȝ层面上,d是在套接字上Q?/p>
Reactor是同?Proactor是异步?
回答Q?/strong>
同步、异步、阻塞和非阻塞的概念
在进行网l编E时Q我们常常见到同步、异步、阻塞和非阻塞四U调用方式。这些方式彼此概念ƈ不好理解。下面是我对q些术语的理解?/p>
同步 所谓同步,是在发Z个功能调用时Q在没有得到l果之前Q该调用׃q回。按照这个定义,其实l大多数函数都是同步调用Q例如sin, isdigit{)。但是一般而言Q我们在说同步、异步的时候,Ҏ那些需要其他部件协作或者需要一定时间完成的d。最常见的例子就?SendMessage。该函数发送一个消息给某个H口Q在Ҏ处理完消息之前,q个函数不返回。当Ҏ处理完毕以后Q该函数才把消息处理函数所q回?LRESULTD回给调用者?/p>
异步 异步的概念和同步相对。当一个异步过E调用发出后Q调用者不能立d到结果。实际处理这个调用的部g在完成后Q通过状态、通知和回调来通知调用者。以 CAsycSocketcMؓ例(注意QCSocket从CAsyncSocketzQ但是v功能已经由异步{化ؓ同步Q,当一个客L通过调用 Connect函数发出一个连接请求后Q调用者线E立d以朝下运行。当q接真正建立h以后Qsocket底层会发送一个消息通知该对象。这里提到执?部g和调用者通过三种途径q回l果Q状态、通知和回调。可以用哪一U依赖于执行部g的实玎ͼ除非执行部g提供多种选择Q否则不受调用者控制。如果执行部 件用状态来通知Q那么调用者就需要每隔一定时间检查一ơ,效率很低(有些初学多线E编E的人,dƢ用一个@环去查某个变量的|q其实是一U很严重 的错误)。如果是使用通知的方式,效率则很高,因ؓ执行部g几乎不需要做额外的操作。至于回调函敎ͼ其实和通知没太多区别?/p>
d d调用是指调用l果q回之前Q当前线E会被挂赗函数只有在得到l果之后才会q回。有Z怼把阻塞调用和同步调用{同hQ实际上他是不同的。对于同 步调用来_很多时候当前线E还是激zȝQ只是从逻辑上当前函数没有返回而已。例如,我们在CSocket中调用Receive函数Q如果缓冲区中没有数 据,q个函数׃一直等待,直到有数据才q回。而此Ӟ当前U程q会l箋处理各种各样的消息。如果主H口和调用函数在同一个线E中Q除非你在特D的界面?作函C调用Q其实主界面q是应该可以h。socket接收数据的另外一个函数recv则是一个阻塞调用的例子。当socket工作在阻塞模式的时候, 如果没有数据的情况下调用该函敎ͼ则当前线E就会被挂vQ直到有数据为止?/p>
非阻?/strong> 非阻塞和d的概늛对应Q指在不能立d到结果之前,该函C会阻塞当前线E,而会立刻q回?/p>
对象的阻塞模式和d函数调用 对象是否处于d模式和函数是不是d调用有很强的相关性,但是q不是一一对应的。阻塞对象上可以有非d的调用方式,我们可以通过一定的API去轮询状 态,在适当的时候调用阻塞函敎ͼ可以避免阻塞。而对于非d对象Q调用特D的函数也可以进入阻塞调用。函数select是q样的一个例子?/p>
d通信
--------------------------------------------------------------------------------
通过重叠通信和计在许多pȝ能提高性能。由一个智能通信控制器自动地执行通信的系l是真实的。轻Q重U烦是取得这U重叠的一U机制。导致好性能?一个可选的机制是用非d通信。一个阻塞发送开始调用初始化q个发送操作,但不完成它。在q个消息被从q个发送缓存拷Z前,q个发送开始调用将q回?需要一个独立的“发送完?#8221;调用完成q个通信Q例如,验从发送缓存拷出的数据。用适当的硬Ӟ在发送被初始化后和它完成以前Q来自发送者存储的数据转换 可以和在发送者完成的计算同时q行。类似地Q一个非d“接收开始调?#8221;初始化这个接收操? 但不完成它。在一个消息被存入q个接收~存以前Q这个调用将q回。须要一个独立的“接收完成”调用完成q个接收操作Qƈ验被接收到这个接收缓存的数据?用适当的硬Ӟ在接收操作初始化后和它完成以前,到接收者存储的数据转换可以和计同时进行。非d接收的用虽着信息较早地在接收~存位置被提供,也可 以避免系l缓存和存储器到存储器拷贝?/p>
非阻塞发送开始调用能使用与阻塞发送一L四种模式: 标准, ~存, 同步和准备好模式。这些具有同L意义。无Z个匹配接收是否已dQ能开始除“准备?#8221;以外的所有模式的发送;只要一个匹配接收已dQ就能开始一个非 d“准备?#8221;发送。在所有情况下Q发送开始调用是局部的Q无论其它进E的状态如何,它立刻返回。如果这个调用得一些系l资源用完,那么它将p|q返?一个错误代码。高质量的MPI实现应保证这U情况只?#8220;病?#8221;时发生。即Q一个MPI实现能支持大数量挂起非d操作。
当数据已被从发送缓存拷出时Q这个发送完成调用返回。它可以带有附加的意义,q取决于发送模式。
如果发送模式是“同步?#8221;Q那么只有一个匹配接收已开始这个发送才能完成。即Q一个接收已被登入,q已和这个发送匹配。这Ӟq个发送完成调用是?局部的。注意,在接收完成调用发生以前,如果一个同步、非d发送和一个非d接收匚w, 它可以完成?发送者一“知道”转换结束,它就能完成,但在接收?#8220;知道”转换结束以?。
如果发送模式是“~存”Qƈ没有挂v接收Q那么消息必被~存。这Ӟ发送完成调用是局部的Q而且无论一个匹配接收的状态如何,它必L功。
如果发送模式是标准的,同时q个消息被缓存,那么在一个匹配接收发生以前,发送结束调用可以返回。另一斚wQ发送完成直C个匹配接收发生才可以完成Qƈ且这个消息已被拷到接收缓存。
非阻塞发送能被用d接收匚wQ反q来也可以?/p>
l用L. 一个发送操作的完成, 对于标准模式可以被gq? 对于同部模式必须延迟, 直到一个匹配接收登入。这两种情况下非d发送的使用允许发送者提前于接收者进行,以便在两q程的速度斚wQ计更容忍波动。
~存和准备好模式中的非阻塞发送有一个更有限的媄响。一可能一个非d发送将q回Q而一个阻塞发送将在数据被从发送者存储拷出后q回。只要在数据拯能和计算同时的情况下Q非d发送的使用有优炏V?/p>
消息发送模式隐含着由发送者初始化通信。当发送者初始化通信(数据被直接移到接收缓? q不要求排队一个挂起发送请? Ӟ如果一个接收已dQ这个通信一般将有较低的额外负担。但是,只在匚w发送已发生后,一个接收操作能完成。当非阻塞接收等待发送时Q没有阻塞接Ӟ?的用允许得到较低的通信额外负担。(l用Ll束Q?/p>
原文出处Q?a >http://www.kuqin.com/networkprog/20090221/35947.html
]]>OpenMPq行E序设计 http://www.shnenglu.com/jianlinzhang/archive/2009/05/14/82906.html张徏?/dc:creator>张徏?/author>Thu, 14 May 2009 01:11:00 GMT http://www.shnenglu.com/jianlinzhang/archive/2009/05/14/82906.html http://www.shnenglu.com/jianlinzhang/comments/82906.html http://www.shnenglu.com/jianlinzhang/archive/2009/05/14/82906.html#Feedback 0 http://www.shnenglu.com/jianlinzhang/comments/commentRss/82906.html http://www.shnenglu.com/jianlinzhang/services/trackbacks/82906.html
OpenMP的指令有以下一些:
parallel Q用在一个代码段之前Q表CD代码将被多个线Eƈ行执?/div>
for Q用于for循环之前Q将循环分配到多个线E中q行执行Q必M证每ơ@环之间无相关性?/div>
parallel for Q?parallel ?for语句的结合,也是用在一个for循环之前Q表Cfor循环的代码将被多个线Eƈ行执行?/div>
sections Q用在可能会被ƈ行执行的代码D之?/div>
parallel sections Qparallel和sections两个语句的结?/div>
critical Q用在一D代码界区之前
single Q用在一D只被单个线E执行的代码D之前,表示后面的代码段被单线E执行?/div>
flush Q?/div>
barrier Q用于ƈ行区内代码的U程同步Q所有线E执行到barrier时要停止Q直到所有线E都执行到barrier时才l箋往下执行?/div>
atomic Q用于指定一块内存区域被制动更新
master Q用于指定一D代码块׃U程执行
ordered Q?用于指定q行区域的@环按序执行
threadprivate , 用于指定一个变量是U程U有的?/div>
OpenMP除上q指令外Q还有一些库函数Q下面列出几个常用的库函敎ͼ
omp_get_num_procs , q回q行本线E的多处理机的处理器个数?/div>
omp_get_num_threads , q回当前q行区域中的zdU程个数?/div>
omp_get_thread_num , q回U程?/div>
omp_set_num_threads , 讄q行执行代码时的U程个数
omp_init_lock , 初始化一个简单锁
omp_set_lock Q?上锁操作
omp_unset_lock Q?解锁操作Q要和omp_set_lock函数配对使用?/div>
omp_destroy_lock Q?omp_init_lock函数的配Ҏ作函敎ͼ关闭一个锁
OpenMP的子句有以下一?/div>
private, 指定每个U程都有它自q变量U有副本?/span>
firstprivate Q?/span> 指定每个U程都有它自q变量U有副本Qƈ且变量要被承主U程中的初倹{?/span>
lastprivate Q?/span> 主要是用来指定将U程中的U有变量的值在q行处理l束后复制回ȝE中的对应变量?/span>
reduce Q?/span> 用来指定一个或多个变量是私有的Qƈ且在q行处理l束后这些变量要执行指定的运?/span>
nowait Q?/span> 忽略指定中暗含的{待
num_threads Q?/span> 指定U程的个?/span>
schedule Q?/span> 指定如何调度 for 循环q代
shared Q?/span> 指定一个或多个变量为多个线E间的共享变?/span>
ordered Q?/span> 用来指定 for 循环的执行要按顺序执?/span>
copyprivate Q?/span> 用于 single 指o中的指定变量为多个线E的׃n变量
copyin Q?/span> 用来指定一?/span>threadprivate 的变量的D用主U程的D行初始化?/span>
default Q?/span> 用来指定q行处理区域内的变量的用方式,~省?/span>shared
文章出处Q?br>
http://blog.csdn.net/drzhouweiming/archive/2006/08/28/1131537.aspx http://blog.csdn.net/drzhouweiming/archive/2006/09/04/1175848.aspx
]]>
office 2007正版验证 http://www.shnenglu.com/jianlinzhang/archive/2009/05/11/82532.html张徏?/dc:creator>张徏?/author>Mon, 11 May 2009 01:23:00 GMT http://www.shnenglu.com/jianlinzhang/archive/2009/05/11/82532.html http://www.shnenglu.com/jianlinzhang/comments/82532.html http://www.shnenglu.com/jianlinzhang/archive/2009/05/11/82532.html#Feedback 7 http://www.shnenglu.com/jianlinzhang/comments/commentRss/82532.html http://www.shnenglu.com/jianlinzhang/services/trackbacks/82532.html Keygen: 点击下蝲此文?/font> VBQF2-6K94C-KCT26-R4XQF-C2QQ8 GM26K-7MYV2-338DJ-4DKMG-DTJBJ CTKXX-M97FT-89PW2-DHKD3-74MYJ(Enterprise密钥,2009-03-25 10:29:53试通过验证) 重新输入序列LҎ:HKEY_LOCAL_MACHINE\Software\Microsoft\Office\12.0\Registration\{90120000-0030-0000-0000-0000000FF1CE},删除子键DigitalProductID,ProductName及ProductID.重新打开Office׃提示输入序列? 已经安装Office2007的直接进行以下步? 2:打开微Y正版验证的网?http://www.microsoft.com/genuine/default.aspx?displaylang=zh-cn 3:验证office2007,安装验证控g,验证昄p|! 4:用附件内OGACheckControl.dll文g:版本号ؓ:1.7.105.14,替换windows\system32\ 目录下同名文件?br>OGACheckControl.dll文g复制_脓到windows\system32\ 目录下即可替?64位系lؓsystem64\目录? 注意:OGACheckControl.dll文g的版本号与系lwindows\system32\下同名文件版本号一?br>Dll下蝲: 点击下蝲此文?/font> 5:再次验证office2007,通过微Y的正版验? 注意:2008q?0?0日微软更新OGACheckControl.dll文g,最新版本号?1.7.105.14,在未替换OGACheckControl.dll文g不能通过正版验证前不要打开Moffice2007lg,以免出现"星星"警告! 版本号ؓ"1.7.111.0"的OGACheckControl.dll文g: 点击下蝲此文?/font> 已经不幸中招?星星"警告?L附g中OGA卸蝲工具,解压后点鼠标右键中卸?直接点击不能卸蝲,卸蝲OGACheckControl.dll文g,重启计算?更换office安装序列?用附件中OGACheckControl.dll重新替换pȝwindows\system32\ 下同名文?再激zoffice2007. 星星卸蝲: 点击下蝲此文?/font> 或者干脆结束掉星星q替换掉星星E序.可用下面的批处理文g. 点击下蝲此文?/font> Office下蝲(推荐q雷): 企业?ftp://ribbitar.3322.org/Soft/MicrosoftOfficeEnterprise2007.iso 专业?ftp://ribbitar.3322.org/Soft/MicrosoftOfficeProfessionalPlus2007.iso 转蝲于:http://1vr.cn/article.asp?id=411
]]> char* String CString比较 http://www.shnenglu.com/jianlinzhang/archive/2009/05/06/82015.html张徏?/dc:creator>张徏?/author>Wed, 06 May 2009 02:14:00 GMT http://www.shnenglu.com/jianlinzhang/archive/2009/05/06/82015.html http://www.shnenglu.com/jianlinzhang/comments/82015.html http://www.shnenglu.com/jianlinzhang/archive/2009/05/06/82015.html#Feedback 0 http://www.shnenglu.com/jianlinzhang/comments/commentRss/82015.html http://www.shnenglu.com/jianlinzhang/services/trackbacks/82015.html CString/string 区别及其转化
利用MFCq行~程Ӟ我们从对话框中利用GetWindowText得到的字W串是CStringcdQCString是属于MFC的类。而一些标准C/C++库函数是不能直接对CStringcdq行操作的,所以我们经帔R到将CStringcd转化char*{等其他数据cd的情c这里ȝ备忘于此Q?/span>
首先要明,标准C中是不存在stringcd的,string是标准C++扩充字符串操作的一个类。但是我们知道标准C中有string.hq个头文Ӟq里要区分清楚,此string非彼string。string.hq个头文件中定义了一些我们经常用到的操作字符串的函数Q如Qstrcpy、strcat、strcmp{等Q但是这些函数的操作对象都是char*指向的字W串?而C++的stringcL作对象是stringcd字符Ԍ该类重装了一些运符Q添加了一些字W串操作成员函数Q得操作字W串更加方便。有的时候我们要string串和char*串配合用,所以也会涉及到q两个类型的转化问题?br> 1.CString和string的{?/strong>
string str = " ksarea " ; CString cstr ( str . c_str ()) ; // 或者CString cstr(str.data());初始化时才行 cstr = str . c_str () ; 或?/span>cstr = str . data () ; str = cstr . GetBuffer ( 0 ) ; //CString -> string cstr . format ( " %s " , str . c_str ()) ; //string->CString cstr . format ( " %s " , str . data ()) ; //string->CString str = LPCSTR ( cstr ) ; //CString->string /*c_str() 和data()区别是:前者返回带'\0'的字W串Q后者则q回不带'\0'的字W串*/
2.CString 和int的{?/span>
inti = 123 ; CString str ; str . format ( " %d " , i ) ; //int->CString 其他的基本类型{化类?/span>i = atoi ( str ) ; //CString->int q有(atof,atol)
3.char* 和CString的{?/span>
CString cstr = " ksarea " ; char* ptemp = cstr . getbuffer ( 0 ) ; char* str ; strcpy ( str , ptemp ) ; //CString->char* cstr . releasebuffer ( - 1 ) ; char* str = " lovesha " ; CString cstr = str ; //char*->CString string cd不能直接赋值给CString
至于int与float、string与char*之间的{化可以用强制{化,或者标准库函数q行。对于CString与其他类型的转化Ҏ很多Q但其实都殊途同归,朝着一个方向即类型首先{化ؓchar*cdQ因为char*是不同类型之间的桥梁。得到char*cdQ{化ؓ其他cd非常容易了?/span>
主要有以下文章:
http://blog.csdn.net/bitxinhai/archive/2008/04/14/2292014.aspx http://www.vczx.com/article/show.php?id=845http://www.vczx.com/article/show.php?id=846
]]>
破解qq的一pd问题 http://www.shnenglu.com/jianlinzhang/archive/2009/05/04/81834.html张徏?/dc:creator>张徏?/author>Mon, 04 May 2009 08:15:00 GMT http://www.shnenglu.com/jianlinzhang/archive/2009/05/04/81834.html http://www.shnenglu.com/jianlinzhang/comments/81834.html http://www.shnenglu.com/jianlinzhang/archive/2009/05/04/81834.html#Feedback 0 http://www.shnenglu.com/jianlinzhang/comments/commentRss/81834.html http://www.shnenglu.com/jianlinzhang/services/trackbacks/81834.html 要看讉K受限的QQI间很简单啊,用手? 在地址栏里输入 http://qqxoo.com/main.html?qqid= 80224567 q样可能看Ҏ的空? http://qqshow-user.tencent.com/80224567 /11/00 看MM的QQl? http://shuqian.qq.com/80224567 / QQ 书签 http://h.qbar.qq.com/80224567 q个是看她的Q? http://shop.paipai.com/80224567 看MM的拍? http://wenwen.soso.com/z/ShowUser.e?sp=80224567 q个是什么呢Q问? http://images.5d6d.net/dz61/smilies/default/mad.gif[/img]Q]http://wpa.qq.com/pa?p=1Q ?4 q个是查看好友在不在qq个?QMM是不是在U? 用手工的是很?不信p?反正也就一分钟 PS: U色部分Ҏ你想的QQ可以了 原帖来自Q?a >http://qzone.qq.com/blog/80224567-1239195902
]]>
ۺϳ˾þС˵ |
wwwԾþþcom |
ݺݾþۺ˲ |
þþƷ91þ鶹 |
AVþþƷ |
þAVĻ |
˾þۺij |
ĻþӰԺ |
99REþþƷﶼǾƷ |
þ99Ʒþþþþ |
999Ʒþþþþ |
þþþƷĻ |
ۿƷþ |
պŷۺϾþӰԺDs
|
þþþƷþþþþ |
777þþƷһ |
ƷþþþþҰ |
þþƷһպ
|
þùۺϾƷ |
AŮAVۺϾþþ |
þþþAVƬ |
ɫۺϾþþþۺһ |
þó鱬Ļ |
ƷѾþ |
ձWVһһþ㽶 |
Ʒ99þþƷ |
þþþavӰ |
þһ |
Ʒþþþþ |
99þùۺϾƷӰԺ |
þþùƵ |
˾þ91 |
þþȹ͵ۺ |
ƷþӰԺ |
þþƷAV㽶 |
þþùƷ |
þۺϹapp |
91þþһȫ |
ҹþþþС˵ |
Ļ˾Ʒþò |
¶ۺϼ¾þ |