转:win32下的堆管理系统
转:https://bbs.pediy.com/thread-224136.htm
准备刷漏洞战争中的堆溢出部分,但是对于堆的了解较少,在这里记录一下关于堆的学习记录,有错误请各位大大拍砖
参考:
- 《软件调试》
- 《0day安全 软件漏洞分析技术》
win32下的堆管理系统:
1. win32堆管理器
win32堆管理器由NTDLL.dll实现,目的是为用户态的应用程序提供内存服务,从实现角度上来讲,内核态的池管理器和用户态的win32堆管理器默用的是同一套基础代码,它们以运行时的方式存在于ntdll.dll和ntosknrl.exe模块中。
2. CRT堆管理器
- CRT由C运行时库创建,CRT创建的堆有三种模式,分别是SBH,ODLSBH和System Heap模式,CRT运行时库选择一种模式创建相应的堆。
- 对于SBH和OLDSBH模式来说,CRT堆会从堆管理器中批发大块的内存,然后分割成小块的内存供程序使用,对于系统模式,CRT堆只是将堆分配请求转发给它基于的win32堆。因此处于系统模式的CRT堆只是对win32堆的简单封装。
win32堆
1.体系结构
应用程序通过堆管理器提供的接口来分配或者是释放内存,整个堆管理器由堆管理api,前端堆,后端堆组成。在处理内存的分配和释放的时候,前端堆先做处理,前端堆有三种选择:none,预读列表(快表,lookaside-list),LFH(低碎片堆)。
2.堆的内部结构
和堆相关的数据结构主要有以下几个:
- _HEAP
- _HEAP_SEGMENT
- _HEAP_ENTRY
- _HEAP_FREE_ENTRY
堆管理器通过_HEAP来记录和维护堆的管理信息,在_HEAP结构中,可能存在一个或者若干个_HEAP_SEGMENT的信息。在我们创建堆时,堆管理器必然会像操作系统申请一块内存空间,那么申请的内存大小和这段内存空间的描述信息就由_HEAP_SEGMENT记录。在每一个_HEAP_SEGMENT结构中,可能存在若干个_HEAP_ENTRY和_HEAP_FREE_ENTRY结构,其中_HEAP_ENTRY和_HEAP_FREE_ENTRY都是对堆块的描述,只不过_HEAP_FREE_ENTRY描述的是空闲的堆快结构,而由_HEAP_ENTRY描述的不一定都是空闲的堆块。
其中_HEAP_ENTRY和_HEAP_FREE_ENTRY的结构体如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
0 : 000 > dt _HEAP_ENTRY ntdll!_HEAP_ENTRY + 0x000 Size : Uint2B + 0x002 PreviousSize : Uint2B + 0x000 SubSegmentCode : Ptr32 Void + 0x004 SmallTagIndex : UChar + 0x005 Flags : UChar + 0x006 UnusedBytes : UChar + 0x007 SegmentIndex : UChar 0 : 000 > dt ntdll!_HEAP_FREE_ENTRY + 0x000 Size : Uint2B + 0x002 PreviousSize : Uint2B + 0x000 SubSegmentCode : Ptr32 Void + 0x004 SmallTagIndex : UChar + 0x005 Flags : UChar + 0x006 UnusedBytes : UChar + 0x007 SegmentIndex : UChar + 0x008 FreeList : _LIST_ENTRY |
- ps:上面两个结构体中比较坑的是,在xp sp3下,通过windbg查看_HEAP_ENTRY和_HEAP_FREE_ENTRY结构体中的第四个字段为SmallTagIndex,但实际上这个字段应该是安全cookie,算法如下:_HEAP._HEAP_ENTRY.cookie=_HEAP_ENTRY.cookie^((BYTE)&_HEAP_ENTRY/8)
- 在win7下,直接用_HEAP_ENTRY和_HEAP_FREE_ENTRY查看数据,会存在问题,需要用_HEAP.ENCODING字段进行解密。
_HEAP结构
windows xp下的_HEAP结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
0 : 000 > dt ntdll!_HEAP 003b0000 + 0x000 Entry : _HEAP_ENTRY + 0x008 Signature : 0xeeffeeff ;heap结构签名 + 0x00c Flags : 0x50001060 ;堆属性 + 0x010 ForceFlags : 0x40000060 ; + 0x014 VirtualMemoryThreshold : 0xfe00 ;最大堆块大小 + 0x018 SegmentReserve : 0x100000 + 0x01c SegmentCommit : 0x2000 + 0x020 DeCommitFreeBlockThreshold : 0x200 + 0x024 DeCommitTotalFreeThreshold : 0x2000 + 0x028 TotalFreeSize : 0x130 ;空闲块总大小,以粒度为单位 + 0x02c MaximumAllocationSize : 0x7ffdefff ;堆可分配的最大内存 + 0x030 ProcessHeapsListIndex : 6 ;堆在peb.processheaps数组中的索引 + 1 + 0x032 HeaderValidateLength : 0x608 + 0x034 HeaderValidateCopy : (null) + 0x038 NextAvailableTagIndex : 0 + 0x03a MaximumTagIndex : 0 + 0x03c TagEntries : (null) + 0x040 UCRSegments : (null) + 0x044 UnusedUnCommittedRanges : 0x003b0598 _HEAP_UNCOMMMTTED_RANGE + 0x048 AlignRound : 0x17 + 0x04c AlignMask : 0xfffffff8 + 0x050 VirtualAllocdBlocks : _LIST_ENTRY [ 0x3b0050 - 0x3b0050 ] + 0x058 Segments : [ 64 ] 0x003b0640 _HEAP_SEGMENT + 0x158 u : __unnamed + 0x168 u2 : __unnamed + 0x16a AllocatorBackTraceIndex : 0 + 0x16c NonDedicatedListLength : 1 + 0x170 LargeBlocksIndex : (null) + 0x174 PseudoTagEntries : (null) + 0x178 FreeLists : [ 128 ] _LIST_ENTRY [ 0x3b0688 - 0x3b0688 ];空闲块 + 0x578 LockVariable : 0x003b0608 _HEAP_LOCK + 0x57c CommitRoutine : (null) + 0x580 FrontEndHeap : (null) + 0x584 FrontHeapLockCount : 0 + 0x586 FrontEndHeapType : 0 '' + 0x587 LastSegmentIndex : 0 '' |
在这个结构体中,FreeLists是一个由128个LIST_ENTRY结构体组成的结构体数组,在调用HeapCreate时,Freelists[0]指向尾块,尾块也就是堆刚创建出时最大的一个空闲块,数组中的其他元素指向自己。
3.创建进程时操作系统为进程创建的默认堆:
ntdll!KiUserApcDispather->ntdll!_LdrpInitialize->ntdll!LdrplInitializeProcess->ntdll!RtlCreateHeap,创建好的堆的句柄回保存在PEB结构的ProcessHeap字段中,PEB中关于堆的字段如下:
1
2
3
4
5
6
7
|
0 : 000 > dt ntdll!_PEB + 0x018 ProcessHeap : Ptr32 Void / / 堆句柄 + 0x078 HeapSegmentReserve : Uint4B / / 默认堆的保留大小: 1MB + 0x07c HeapSegmentCommit : Uint4B / / 默认堆的提交大小: 8kb + 0x088 NumberOfHeaps : Uint4B / / 进程中堆的总数 + 0x08c MaximumNumberOfHeaps : Uint4B / / ProcessHeaps数组中数组元素的个数 + 0x090 ProcessHeaps : Ptr32 Ptr32 Void / / 这个数组用来保存进程中创建的堆的句柄 |
4.私有堆:
创建:
可以通过HeapCreate这个api来创建属于进程的私有堆,这个api实际上回去调用RtlCreateHeap函数,创建完毕之后会将创建好的堆句柄保存到peb结构中。HANDLE WINAPI HeapCreate(DWORD flOptions,SIZE_T dwInitialSize, SIZE_T dwMaximumSize)
这个api中,flOptions下面三个可选项:
- HEAP_CREATE_ENABLE_EXECUTE 允许执行堆中的代码,也就是这时创建出的堆具有可执行属性。
- HEAP_GENERATE_EXCEPTIONS 使用异常来报告HeapAlloc和HeapReAlloc的错误而不是通过返回NULL。
- HEAP_NO_SERIALIZE 当堆函数访问这个堆时,不需要进行串行化控制。这么做可以提高操作堆的速度,但是在多线程同时操作堆时,可能出现问题。当创建堆时指定这个参数时,不能启用低碎片堆(LFH)。
在windbg中可以使用!heap -h指令来查看进程中的所有堆。!heap -h的查询结果也就是peb.ProcessHeaps中的值。
销毁:
HeapDestory->ntdll!RtlDestroyHeap->NtFreeVirtualMemory。
ntdll!RtlDestroyHeap会将PEB堆列表中的堆要销毁堆的堆句柄移除掉,然后通过NtFreeVirtualMemory函数向内存管理器归还内存。
应用程序不应该也不许销毁默认堆,当进程退出和销毁进程对象时,系统都会调用MnCleanProcessSpace函数。
堆内存的申请和释放
通过HeapAlloc这个api可以从堆中分配空间出来,LPVOID WINAPI HeapAlloc(HANDLE hHeap,DWORD dwFlags,SIZE_T dwBytes)
,dwFlags有下面几个选项:
- HEAP_GENERATE_EXCEPTIONS 系统通过返回异常而不是返回NULL来报告错误
- HEAP_NO_SERIALIZE 不对堆进行串行话控制。
- HEAP_ZERO_MEMORY 分配的内存将被初始化为0。
ps:指定这些值中的任何值将覆盖使用HeapCreate创建堆时指定的对应值 。
也可以使用malloc,calloc或者是new运算符来从堆中分配内存,上面提到CRT堆有三种模式,大多数情况下,运行时库都会选择系统模式,此时CRT堆建立在win32堆之上。
通过HeapFree这个api可以从释放HeapAlloc申请处的内存空间,free或者是delete最终都会跳到这个api上来释放内存。
winxp 堆内存释放和合并-空闲双向链表:
实验代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include <stdio.h> #include <windows.h> main() { HLOCAL h1,h2,h3,h4,h5,h6; HANDLE hp; hp = HeapCreate( 0 , 0x1000 , 0x10000 ); getchar(); __asm int 3 h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 3 ); h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 5 ); h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 6 ); h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 8 ); h5 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 19 ); h6 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 24 ); HeapFree(hp, 0 ,h1); / / free to freelist[ 2 ] HeapFree(hp, 0 ,h3); / / free to freelist[ 2 ] HeapFree(hp, 0 ,h5); / / free to freelist[ 4 ] HeapFree(hp, 0 ,h4); / / coalese h3,h4,h5,link the large block to freelist[ 8 ] return 0 ; } |
执行程序之后用windbg附加,然后f5,断到int 3,在windbg中查看空闲表
1
2
3
4
5
|
0 : 000 >dd 0x003a0000 + 0x178 003a0178 003a0688 003a0688 003a0180 003a0180 003a0188 003a0188 003a0188 003a0190 003a0190 003a0198 003a0198 003a0198 003a01a0 003a01a0 003a01a8 003a01a8 003a01a8 003a01b0 003a01b0 |
Heap.FreeLists[0]的flink和blink分别都指向0x003a0688.通过!heap -a 003a0000
查到的结果,我们来看分配到的堆块结构,在windbg中输入!heap -x 003a0640
或者是dt ntdll!_HEAP_ENTRY
来查看堆结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
0 : 000 > !heap - x 003a0640 Entry User Heap Segment Size PrevSize Unused Flags - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 003a0640 003a0648 003a0000 003a0640 40 640 0 busy 0 : 000 > dt ntdll!_HEAP_ENTRY 003a0640 + 0x000 Size : 8 + 0x002 PreviousSize : 0xc8 + 0x000 SubSegmentCode : 0x00c80008 + 0x004 SmallTagIndex : 0 '' + 0x005 Flags : 0x1 '' + 0x006 UnusedBytes : 0 '' + 0x007 SegmentIndex : 0 ' |
其中_HEAP_ENTRY.Size为堆块的大小/堆块分配粒度,堆块分配粒度一般都为8,可以用!heap -v 堆基址来查看
然后单步执行完 h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,3),观察空闲块的变化
1
2
3
4
5
|
0 : 000 > dd 0x003a0000 + 0x178 003a0178 003a0698 003a0698 003a0180 003a0180 003a0188 003a0188 003a0188 003a0190 003a0190 003a0198 003a0198 003a0198 003a01a0 003a01a0 003a01a8 003a01a8 003a01a8 003a01b0 003a01b0 |
此时Heap.FreeLists[0]的flink和blink分别都指向0x003a0698,在windbg中输入!heap -x 0x003a0698
或者是dt ntdll!_HEAP_FREE_ENTRY 0x003a0698-8
来查看堆结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
0 : 000 > !heap - x 003a0698 Entry User Heap Segment Size PrevSize Unused Flags - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 003a0690 003a0698 003a0000 003a0640 970 10 0 free last 0 : 000 > dt ntdll!_HEAP_FREE_ENTRY 003a0698 - 8 + 0x000 Size : 0x12e + 0x002 PreviousSize : 2 + 0x000 SubSegmentCode : 0x0002012e + 0x004 SmallTagIndex : 0 '' + 0x005 Flags : 0x10 '' + 0x006 UnusedBytes : 0 '' + 0x007 SegmentIndex : 0 '' + 0x008 FreeList : _LIST_ENTRY [ 0x3a0178 - 0x3a0178 ] |
在_HEAP_FREE_ENTRY中多了一个LIST_ENTRY成员,而这个成员的flink和blink都只想freelist[0]。单步执行完HeapFree(hp,0,h1);
在windbg中观察下内存的变化:
1
2
3
4
5
6
7
8
|
0 : 000 > dd 003a0000 + 0x178 003a0178 003a0708 003a0708 003a0180 003a0180 003a0188 003a0688 003a0688 003a0190 003a0190 003a0198 003a0198 003a0198 003a01a0 003a01a0 003a01a8 003a01a8 003a01a8 003a01b0 003a01b0 003a01b8 003a01b8 003a01b8 003a01c0 003a01c0 003a01c8 003a01c8 003a01c8 003a01d0 003a01d0 003a01d8 003a01d8 003a01d8 003a01e0 003a01e0 |
可以看到Heap.FreeLists[2]成员的flink和blink分别都指向了0x003a0688,而在此之前,Heap.FreeLists[2]的两个成员都指向自己。单步执行完HeapFree(hp,0,h5)
观察下内存结构
1
2
3
4
5
6
|
0 : 000 > dd 003a0000 + 0x178 003a0178 003a0708 003a0708 003a0180 003a0180 003a0188 003a0688 003a06a8 003a0190 003a0190 003a0198 003a06c8 003a06c8 003a01a0 003a01a0 003a01a8 003a01a8 003a01a8 003a01b0 003a01b0 003a01b8 003a01b8 003a01b8 003a01c0 003a01c0 |
FreeList[0].flink和blink都指向最后一个空闲块003a0708,FreeList[2].flink指向第一次释放的堆块,FreeList[2].blink指向第二次释放的堆块。在windbg中查看下这两个空闲块的结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
0 : 000 > dt ntdll!_HEAP_FREE_ENTRY 003a0688 - 8 + 0x000 Size : 2 + 0x002 PreviousSize : 8 + 0x000 SubSegmentCode : 0x00080002 + 0x004 SmallTagIndex : 0xcb '' + 0x005 Flags : 0 '' + 0x006 UnusedBytes : 0xd '' + 0x007 SegmentIndex : 0 '' + 0x008 FreeList : _LIST_ENTRY [ 0x3a06a8 - 0x3a0188 ] 0 : 000 > dt ntdll!_HEAP_FREE_ENTRY 003a06a8 - 8 + 0x000 Size : 2 + 0x002 PreviousSize : 2 + 0x000 SubSegmentCode : 0x00020002 + 0x004 SmallTagIndex : 0xcf '' + 0x005 Flags : 0 '' + 0x006 UnusedBytes : 0xa '' + 0x007 SegmentIndex : 0 '' + 0x008 FreeList : _LIST_ENTRY [ 0x3a0188 - 0x3a0688 ] |
观察空闲块和Freelist表结构,我们可以得出结论:每个空闲块的前向指针指向前一个空闲块,第一个空闲块的前向指针指向相应的freelist头,每一个空闲块的后向指针指向下一个空闲块,最后一个空闲块的后向指针指向相应的freelist头,而freelist头的前向指针指向最后一个空闲块,freelist头的后向指针指向第一个空闲块,这样就构成了一个双循环链表。
单步执行完HeapFree(hp,0,h4); //coalese h3,h4,h5,link the large block to freelist[8]
,观察下空闲块的结构:
1
2
3
4
5
6
7
8
9
|
0 : 000 > dd 003a0000 + 0x178 003a0178 003a0708 003a0708 003a0180 003a0180 003a0188 003a0688 003a0688 003a0190 003a0190 003a0198 003a0198 003a0198 003a01a0 003a01a0 003a01a8 003a01a8 003a01a8 003a01b0 003a01b0 003a01b8 003a06a8 003a06a8 003a01c0 003a01c0 003a01c8 003a01c8 003a01c8 003a01d0 003a01d0 003a01d8 003a01d8 003a01d8 003a01e0 003a01e0 003a01e8 003a01e8 003a01e8 003a01f0 003a01f0 |
此时三个空闲块从freelist[2],freelist[4]中被摘下,合并之后链入freelist[8].
winxp 堆内存释放-快速单向链表:
快表的结构和空闲表的结构相似,表中元素为单链表表头,组织结构如下:
1
2
3
4
5
6
7
8
9
|
快表 | - - - - - - - - - - - - - - - | | lookaside[ 0 ] | | lookaside[ 1 ] | - > [ 8bytes ] - > [ 8bytes ] | lookaside[ 2 ] | - > [ 16bytes ] | ..............|.................. | lookaside[ 126 ]| | lookaside[ 127 ]| - >[ 1016bytes ] | - - - - - - - - - - - - - - - | |
实验代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include <stdio.h> #include <windows.h> #include <windows.h> main() { HLOCAL h1,h2,h3,h4; HANDLE hp; hp = HeapCreate( 0 , 0x0 , 0x0 ); getchar(); __asm int 3 ; h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 8 ); h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 8 ); h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 16 ); h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 24 ); HeapFree(hp, 0 ,h1);free heap1 to lookaside[ 1 ]; HeapFree(hp, 0 ,h2);free heap2 to lookaside[ 1 ] HeapFree(hp, 0 ,h3);free heap3 to lookaside[ 2 ]; HeapFree(hp, 0 ,h4);free heap4 to lookaside[ 3 ]; h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY, 16 ); / / alloc block from lookaside[ 2 ] return 0 ; } |
执行程序之后用windbg附加,f5,断到int3,然后单步到HeapFree(hp,0,h1)
执行结束,此时观察下内存结构:
1
2
3
4
5
|
0 : 000 > dd 003a0000 + 0x178 003a0178 003a1ee8 003a1ee8 003a0180 003a0180 003a0188 003a0188 003a0188 003a0190 003a0190 003a0198 003a0198 003a0198 003a01a0 003a01a0 003a01a8 003a01a8 003a01a8 003a01b0 003a01b0 |
此时我们观察下空闲块,并没有发现有是释放过的空闲块。在内存中查看下快表:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
0 : 000 > dd 003a0000 + 0x688 l50 003a0688 00000000 00000000 01000004 00000000 003a0698 00000000 00000000 00000000 00000000 003a06a8 00000000 00000004 00000000 00000000 003a06b8 00000000 00000000 01000004 00000000 003a06c8 00000000 00000000 00000000 00000000 003a06d8 00000000 00000000 00000000 00000000 003a06e8 003a1e90 00010001 01000004 00000002 003a06f8 00000002 00000001 00000000 00000000 003a0708 00000000 00000000 00000000 00000000 003a0718 00000000 00000000 01000004 00000001 003a0728 00000001 00000000 00000000 00000000 003a0738 00000000 00000000 00000000 00000000 |
发现在快表结构中多出了第一次我们申请到的地址0x003a1e90,在windbg中查询结果如下:
1
2
3
4
|
0 : 000 > !heap - x 003a1e90 Entry User Heap Segment Size PrevSize Unused Flags - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 003a1e88 003a1e90 003a0000 003a0640 10 1808 8 busy |
和空闲块有所不同的是,堆块的flag为busy。
单步执行完HeapFree(hp,0,h4);free heap4 to lookaside[3];
之后,观察下内存中的块表信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
0 : 000 > dd 003a0000 + 0x688 l50 003a0688 00000000 00000000 01000004 00000000 003a0698 00000000 00000000 00000000 00000000 003a06a8 00000000 00000004 00000000 00000000 003a06b8 00000000 00000000 01000004 00000000 003a06c8 00000000 00000000 00000000 00000000 003a06d8 00000000 00000000 00000000 00000000 003a06e8 003a1ea0 00020002 01000004 00000002 003a06f8 00000002 00000002 00000000 00000000 003a0708 00000000 00000000 00000000 00000000 003a0718 003a1eb0 00010001 01000004 00000001 003a0728 00000001 00000001 00000000 00000000 003a0738 00000000 00000000 00000000 00000000 003a0748 003a1ec8 00010001 01000004 00000001 003a0758 00000001 00000001 00000000 00000000 003a0768 00000000 00000000 00000000 00000000 003a0778 00000000 00000000 01000004 00000000 |
转:win32下的堆管理系统的更多相关文章
- cocos2dx c++ 在mac下写的中文凝视,在win32下编译时不通过
今天遇到个奇怪的问题,在mac下写的程序,加的中文凝视,编译没有问题,可是在win32下(使用的时vs2012, win7 64bit 系统)编译就总是报错 最后在中文凝视后 加一个空格,或者 换行, ...
- win32下用VC扩展PHP全过程
闲着无聊,打算开发一些PHP组件来玩玩,由于在家没有工作环境,遂打算在win32(我的环境是vista)用VC开发DLL模块,费话不 多说了,进入正题: 一.已经在机器上安装PHP环境的就略过,否则先 ...
- win32下利用python操作printer
在win32下操作printer: 1)import win32print 2) 获得默认打印机名: >>> win32print.GetDefaultPr ...
- dijkstra(最短路)和Prim(最小生成树)下的堆优化
dijkstra(最短路)和Prim(最小生成树)下的堆优化 最小堆: down(i)[向下调整]:从第k层的点i开始向下操作,第k层的点与第k+1层的点(如果有)进行值大小的判断,如果父节点的值大于 ...
- Win32 OpenGL 编程( 1 ) Win32 下的 OpenGL 编程必须步骤
http://blog.csdn.net/vagrxie/article/details/4602961 Win32 OpenGL 编程( 1 ) Win32 下的 OpenGL 编程必须步骤 wri ...
- Win32下的中断和异常
本文是Matt Pietrek在1997年月10月的MSJ杂志Under The Hood专栏上发表的文章.中断和异常在DOS时代是整个系统的灵魂,但Windows已将其隐藏到了系统深处.Matt P ...
- 【神经网络与深度学习】【CUDA开发】caffe-windows win32下的编译尝试
[神经网络与深度学习][CUDA开发]caffe-windows win32下的编译尝试 标签:[神经网络与深度学习] [CUDA开发] 主要是在开发Qt的应用程序时,需要的是有一个使用的库文件也只是 ...
- [老文章搬家] [翻译] 深入解析win32 crt 调试堆
09 年翻译的东西. 原文见: http://www.nobugs.org/developer/win32/debug_crt_heap.html 在DeviceStudio的Debug编译模式下, ...
- win32下进程间通信——共享内存
一.引言 在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.WIN32 API提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换 ...
随机推荐
- 前端PHP入门-028-文件操作-掌握级别
作为刚入门我们员经常会干的意见事情是ctrl+c和ctrl+v,鼠标右键删除文件.会control+c(或右键)复制.粘贴文件以及新建文件,还可以设置文件的是否为只读文件等等 可不可以写入修改配置文件 ...
- DLL基本知识
一.生成方式: 使用DEF文件定义导出接口或使用__declspec(dllexport)描述接口,编译链接后生成dll+lib,其中lib是导入库,里面只有对导出接口的描述,而没有具体实现. 二.链 ...
- Asp.Net MVC 自定义登录过滤器
1.新建类BaseController用于统一所有控制器继承扩展,方便扩展登录等过滤器.示例如下: using CloudWave.JustBeHere.JBH_H5.Controllers.Attr ...
- 【BZOJ】3039: 玉蟾宫 悬线法
[题意]给定01矩阵,求最大全1子矩阵.n,m<=1000. [算法]动态规划(悬线法) [题解]★对于01矩阵中的任意一个全1极大子矩阵,都可以在其上边界遇到的障碍点处悬线到下边界的点x,则点 ...
- An impassioned circulation of affection(尺取+预处理)
题目链接:http://codeforces.com/contest/814/problem/C 题目: 题意:给你一个长度为n的字符串,m次查询,每次查询:最多进行k步修改,求字符c(要输入的字符) ...
- filezilla显示隐藏文件
我们在习惯使用flashfxp等工具,但是随着主机商限制较多,这些老的FTP工具不怎么好用了,比如主机商会推荐使用到Filezilla等工具.但是比如息壤主机,我们在管理linux环境下htacess ...
- PHP非常好用的分页类
分页类: <?php /* * ********************************************* * @类名: page * @参数: $myde_total - 总记 ...
- Android Service使用简单介绍
作为一个android初学者,经常对service的使用感到困惑.今天结合Google API 对Service这四大组件之一,进行简单使用说明. 希望对和我一样的初学者有帮助,如有不对的地方,也希望 ...
- PIP安装时报The repository located at pypi.douban.com is not a trusted or secure host and is being ignore
C:\WINDOWS\system32>pip install scrapyCollecting scrapy The repository located at pypi.douban.com ...
- xshell连接Ubuntu虚拟机
Ubuntu系统 1,安装ssh sudo apt-get install openssh-server 2,启动ssh进程 /etc/init.d/ssh start 3,查看进程信息 ps -e ...