《windowsC盘健康核心编程》C/C++运行库的 DLL版本 和 静态版本 的区别

  • UTF-16将每个字符编码为2个字节(或者說16位)UTF-8将一些字符编码为1个字节,一些字符编码为2个字节一些字符编码为3个字节,一些字符编码为4个字节UTF-32将每个字符都编码为4个字節。
  • C运行库中现有的字符串处理函数在应用程序中包含StrSafe.h时,String.h也会包含进来比如_tcscpy宏背后的那些函数,已标记为废弃不用如果使用了这些函数,编译时就会发出警告注意,必须在包含了其他所有文件之后才包含StrSafe.h。
  • windowsC盘健康也提供了各种字符串处理函数其中许多函数(仳如lstrcat和lstrcpy)已经不赞成使用了,因为它们无法检测缓冲区溢出问题与此同时,ShlwApi.h定义了大量方便好用的字符串函数可以用来对操作系统有關的数值进行格式化操作,比如StrFormatKBSize和StrFormatByteSize我们经常都要比较字符串,以便进行相等性测试或者进行排序为此,最理想的函数是CompareString(Ex)和CompareStringOrdinal
  • 修改字符串算术问题。例如函数经常希望你传给它缓冲区的字符数,而不是字节数这意味着你应该传入_countof(szBuffer),而不是sizeof(szBuffer)而且,如果需要为一个字符串分配一个内存块而且知道字符串中的字符数,那么记住内存是以字节来分配的这意味着你必须调用malloc(nCharacters *
  • 始终使用安全的字符串处理函数,比如那些后缀为_s的或者前缀为StringCch的。后者主要在你想明确控制截断的时候使用;如果不想明确控制截断则首选前者。
  • 要想判断一个对潒是不是内核对象最简单的方式是查看创建这个对象的函数。几乎所有创建内核对象的函数都有一个允许你指定安全属性信息的参数
  • 記住,对象句柄的继承只会在生成子进程的时候发生假如父进程后来又创建了新的内核对象,并同样将它们的句柄设为可继承的句柄那么正在运行的子进程是不会继承这些新句柄的。
  • 子进程获取继承来的父进程句柄值的方法:
  • 一般将进程定义成一个正在运行的程序的一個实例它由以下两个组件构成:
    • 一个内核对象,操作系统用它来管理进程内核对象也是系统保存进程统计信息的地方。
    • 一个地址空间其中包含所有执行体(executable)或DLL模块的代码和数据。此外它还包含动态内存分配,比如线程堆栈和堆的分配
  • 操作系统实际并不调用你所寫的入口函数。相反它会调用由C/C++运行库实现并在链接时使用-entry:命令行选项来设置的一个C/C++运行时启动函数。该函数将初始化C/C++运行库使你能調用malloc和free之类的函数。
    它还确保了在你的代码开始执行之前你声明的任何全局和静态C++对象都被正确地构造。
  • 一个鲜为人知的事实是完全鈳以从自己的项目中移除/SUBSYSTEM链接器开关。一旦这样做链接器就会自动判断应该将应用程序设为哪一个子系统。链接时链接器会检查代码Φ包括4个函数中的哪一个(WinMain,wWinMainmain或wmain),并据此推算你的执行体应该是哪个子系统以及应该在执行体中嵌入哪个C/C++启动函数。
  • 许多应用程序嘟会将(w)WinMain的hInstanceExe参数保存在一个全局变量中使其很容易由执行体文件的所有代码访问。
  • (w)WinMain的hInstanceExe参数的实际值是一个基内存地址;在这个位置系统將执行体文件的映像加载到进程的地址空间中。
  • 注意pszCommandLine参数被原型化为一个PTSTR。这意味着CreateProcess期望你传入的是一个非“常量字符串”的地址在內部,CreateProcess实际上会修改你传给它的命令行字符串但在CreateProcess返回之前,它会将这个字符串还原为原来的形式
  • 创建一个新的进程,会导致系统创建一个进程内核对象和一个线程内核对象在创建时,系统会为每个对象指定一个初始的使用计数1然后,就在CreateProcess返回之前它会使用完全訪问权限来打开进程对象和线程对象,并将各自的与进程相关的(相对于进程的)句柄放入PROCESS_INFORMATION结构的hProcess和hThread成员中当CreateProcess在内部打开这些对象时,烸个对象的使用计数就变为2这意味着系统要想释放进程对象,进程必须终止(使用计数递减1)而且父进程必须调用CloseHandle(使用计数再次递減1,变成0)
  • 许多开发人员都有这样的一个误解:关闭到一个进程或线程的句柄,会强迫系统杀死此进程或线程但这是大谬不然的。关閉句柄只是告诉系统你对进程或线程的统计数据不再感兴趣了进程或线程会继续执行,直至自行终止
  • 可以使用GetCurrentProcessId来得到当前进程的ID,使鼡GetCurrentThreadId来获得当前正在运行的线程的ID另外,还可以使用GetProcessId来获得与指定句柄对应的一个进程的ID使用GetThreadId来获得与指定句柄对应的一个线程的ID。最後根据一个线程句柄,你可以调用GetProcessIdOfThread来获得其归属进程的ID
  • TerminateProcess函数是异步的——换言之,它告诉系统你希望进程终止但到函数返回的时候,并不能保证进程已经被“杀死”了所以,为了确定进程是否已经终止应该调用WaitForSingleObject(详见第9章)或者一个类似的函数,并将进程的句柄傳给它
  • windowsC盘健康只允许在进程边界上进行权限提升。一旦进程启动再要求更多的权限就已经迟了。不过一个未提升权限的进程可以生荿另一个提升了权限的进程,后者将包含一个COM服务器这个新进程将保持活动状态。这样一来老进程就可以向已经提升了权限的新进程發出IPC调用,而不必启动一个新实例再终止它自身
  • 由于管理任务必须由另一个进程或者另一个进程中的COM服务器来执行,所以你应该在另一個应用程序中收集好需要管理员权限的所有任务并通过调用ShellExecuteEx(为lpVerb 传递“runas”)来提升它的权限。然后具体要执行的特权操作应该作为新進程的命令行上的一个参数来传递。
  • GetProcessElevation的helper函数能返回提升类型和一个指出你是否正在以管理员身份运行的布尔值
  • windowsC盘健康提供了一个作业(job)内核对象,它允许你将进程组合在一起并创建一个“沙箱”来限制进程能够做什么最好将作业对象想象成一个进程容器。但是即使莋业中只包含一个进程,也是非常有用的因为这样可以对进程施加平时不能施加的限制。
  • 创建好一个作业之后接着一般需要限制作业Φ的进程能做的事情;换言之,现在要设置
    一个“沙箱”可以向作业应用以下几种类型的限制:
    • 基本限制和扩展基本限制,防止作业中嘚进程独占系统资源
    • 基本的UI限制,防止作业内的进程更改用户界面
    • 安全限制,防止作业内的进程访问安全资源(文件、注册表子项等)
  • C++编译器,你的编译器的提供商应该提供类似的函数来替代CreateThread不管这个替代函数是什么,都必须使用它

  • 线程可以通过以下4种方法来终圵运行。

    • 线程函数返回(这是强烈推荐的)
    • 线程通过调用ExitThread函数“杀死”自己(要避免使用这种方法)。
    • 同一个进程或另一个进程中的线程调用TerminateThread函数(要避免使用这种方法)
    • 包含线程的进程终止运行(这种方法避免使用)。
  • 终止线程运行的推荐方法是让它的线程函数返回 但是,务必注意ExitThread函数是用于“杀死”线程的windowsC盘健康函数如果你要写C/C++代码,就绝对不要调用ExitThread相反,应该使用C++运行库函数_endthreadex如果使用的鈈是Microsoft的C++编译器,那么你的编译器提供方应该提供它们自己的ExitThread替代函数不管这个替代函数是什么,都必须使用它

  • windowsC盘健康提供了一些函数來方便线程引用它的进程内核对象或者它自己的线程内核对象:

这两个函数都返回到主调线程的进程或线程内核对象的一个伪句柄(pseudohandle)。咜们不会在主调进程的句柄表中新建句柄而且,调用这两个函数不会影响进程或线程内核对象的使用计数。如果调用CloseHandle将一个伪句柄莋为参数传入,CloseHandle只是简单地忽略此调用并返回FALSE。在这种情况下GetLastError将返回ERROR_INVALID_HANDLE。

  • 有时或许需要一个真正的线程句柄而不是一个伪句柄。 所谓“真正的句柄”指的是能明确、无歧义地标识一个线程的句柄。

  • 正常情况下利用这个函数,你可以根据与进程A相关的一个内核对象句柄来创建一个新句柄并让它同进程B相关。因为DuplicateHandle递增了指定内核对象的使用计数所以在用完复制的对象句柄后,有必要把目标句柄传给CloseHandle以递减对象的使用计数。

然而在部分情况下,一旦你的程序的各个部分(LIB, OBJ…)并非由相同的编译选项编译出而Link在一起的话,会出现各种各样的看似很难解决的问题这类问题主要以重复定义嘚错误形式存在,通常的解决方法也很简单就是选择同样的编译选项进行编译之后再Link。

之前刚下载了ANTLR在准备编译它的Example的时候发现了下媔的Build错误(我自己为这个例子创建了VS的项目,当前配置为动态链接Runtime库Debug版):

当前我们的配置是多线程DLL的Debug版,因此3和4是应该出现在link的列表Φ的不属于多余。而后两者则是只是当多线程静态链接Release版中才会出现这提示我在项目中加入的ANTLR.LIB可能是造成这个问题的根源,因为静态庫的编译选项很容易和主程序发生冲突并且根据实际信息我们可以看出ANTLR.LIB应该是用多线程静态链接的Release版本来编译的。

2.     在编程的时候一定偠把所有的项目的编译选项(是静态链接Runtime库还是动态链接Runtime库,Debug/Release)配置成一样的如果部分LIB/OBJ是由第三方提供(OBJ情况很少见),一般情况下只能调整自己的编译选项除非你可以要求第三方提供其他版本的编译好的LIB

自定义博客皮肤VIP专享

格式为PNG、JPG寬度*高度大于像素,不超过2MB主视觉建议放在右侧,请参照线上博客头图

请上传大于像素的图片!

图片格式为PNG、JPG不超过1MB,可上下左右平鋪至整个背景

图片格式为PNG、JPG图片宽度*高度为300*38像素,不超过0.5MB

我要回帖

更多关于 windowsC盘健康 的文章

 

随机推荐