Windows核心编程(笔记13) 第十六章--第二十六章
改变下记录方式,只写自己觉得需要注意一下的防止出错的地方,或者一些特别重要的点,或者一些感悟。
第十六章 线程栈
第十七章 内存映射文件
1.注意写时复制在内存映射文件中的用处。
2.#pagma data_seg("xxx")...#pagma data_seg()创建共享段。但仅对在两个语句之间已经初始化的变量有效,未初始化的变量则需加上__declspec(allocate("xxx"))来声明。
3.内存映射文件能在映射到的多个视图中保持数据一致,这是因为该文件中的每个页面在内存中只有一份,而这些内存页面只是被映射到了多个进程的地址空间而已。
4.指针保存的是当前进程的地址空间中的地址值,所以若是在一个内存映射文件中准备了一个链表,然后需要映射该文件到另一个进程,这时如果相对于新进程映射的地址基址变了的话,那么指针保存的地址会无效。这时只能通过MapViewOfFileEx指定映射的地址基址来解决。
第十八章 堆
1.堆就是一块预定的地址空间区域。
2.内存碎片是指,已调拨和未调拨的区域混在一起了,导致很多未调拨的区域因大小等原因得不到分配的机会。
3.堆的线程安全性需要注意。
4.如果堆中一个内存块是链表或树的一部分,则给堆realloc时尽量就地增加,不要让其移动。
5.在堆中分配内存时会占用一些额外的内存。
6.GetProcessHeaps也会返回进程默认堆的句柄。
第十九章 DLL基础
第二十章 DLL高级技术
1.注意import和export在头文件中针对库和程序的切换。
2.显式载入DLL不需要在链接属性的输入库里面加上该DLL的lib。
3.为了防止FreeLibrary对DLL的映射从进程地址空间中撤销后,调用ExitThread的代码因不复存在而导致访问违规,可用FreeLibraryAndExitThread代替,该函数执行的指令都在Kernel32.dll中。
4.当LoadLibraryEx使用标志时它和用LoadLibrary载入DLL所得到的句柄是不一样的,即使是同一个文件也不同。
5.DllMain里面只应该执行简单的初始化,也不要调用Load/FreeLibrary等。防止产生循环依赖。
6.程序中任何一个DLL的DllMain函数返回FALSE的话,系统会把该程序所有的文件映像从地址空间中清除,向用户弹框表示程序无法启动,然后终止整个进程。
7.创建主线程时,不会让主线程用DLL_THREAD_ATTCH来调用DllMain函数。
8.DLL_THREAD_ATTCH/DETACH只针对线程的创建和销毁,而无视相关的DLL操作;但DLL_PROCESS_ATTCH/DETACH两者都会响应。
9.进程中对DLL的DllMain的调用是序列化的,一次只让一个线程调用DllMain直到其完成。
10.每个可执行文件(0x00400000)和DLL模块(0x10000000)都有一个首选基地址,它表示在将模块映射到进程的地址空间中时的最佳内存地址。
11.基地址重定位非常重要,能显著提高整个系统的性能。通过模块绑定把程序导入段中所需的DLL的基地址预绑定到进程的地址空间能减少可能的页交换文件和内存间的数据交换,从未减少初始化时间并减少内存使用。
第二十一章 纤程局部存储区
第二十二章 DLL注入和API拦截
1.进程不能创建一个指针来引用属于其他进程的内存。
2.SetWindowHookEx若是挂的全局钩子,那么它对该函数操作完后新建的进程也是有效的。
3.当通过创建远程线程来对别的进程进行注入时,若注入的代码导致远程进程中的执行线程访问违规,那么被终止的是远程进程。
第二十三章 终止处理程序
第二十四章 异常处理程序与软件异常
1.应该避免在try代码块中使用return,continue,break,goto等语句,避免不必要的性能开销。
2.尽量限制在catch或者finally块中代码所做的工作,否则进程很有可能会在finally块执行前突然终止。
3.Vista之前,全局展开默认触发,但Vista开始不再默认触发。
4.try-finally或者try-except必须成对出现,可以嵌套,但不能一对多。
5.返回EXCEPTION_EXECUTE_HANDLER会执行全局展开。
6.只处理我们知道怎么处理的异常。
7.若一个异常发生在try-finally中,但其上层又没有try-except,在Vista之前的系统中,全局展开会在进程结束前发生,finally块会被执行,但Vista之后进程会立刻终止。
8.将return语句置于finally块中可以组织系统完成全局展开,即上层的finally和except块中的代码都不再执行,而只执行正常流程的代码。
9.GetExceptionInformation只能在异常过滤程序中调用。
第二十五章 未处理异常,向量化异常处理与C++异常
第二十六章 错误报告与应用程序恢复
1.SetUnhandledExceptionFilter这玩意儿无法断点跟踪。
2.开发C++程序的话,应使用C++异常,而不是SEH。对于VC而言,其C++异常就是通过SEH实现的。
3.C++异常不能再次执行错误代码。
4.注意应用程序的自动重启与保存异常退出前数据
附录
1.用VC的编译警告等级最高级4来编译项目的话,连Windows头文件都会有很多警告,可以通过:
- #pragram warning(push, 3)
- #include <windows.h>
- #pragram warning(pop)
- #pragram warning(push, 4)
- // include other headers
- // ...
3.注意windowsX.h中各种宏。