e股脑电脑教程网
  • 首 页
  • 操作系统
  • 应用软件
  • 下载工具
  • 影音视频
  • 办公软件
  • 媒体制作
  • 网站建设
  • 平面设计
  • 数据库
  • 程序开发
  • 视频教程
编辑推荐: | 文章搜索:
您现在的位置: e股脑 >> 程序开发 >> ASP.net教程 >> VC++2005快速构建安全的应用程序 >> 教程正文
 
教程搜索
 
 
相关教程
  • C++/CLI实战——HELLO
  • VC编写简单的序列号(SN)填写器
  • Visual Studio 2005体验泛型编程
  • C++/CLI基本数据类型探索
  • 用托管C++编写Windows服务
  • Visual C++ 2005图像编程之属性设置栏
  • Visual C++ 2005图像编程之工具栏
  • Visual C++ 2005图像编程之预备知识
  • 把其他C/C++编译器集成到VC2005中
  • VC.NET实现清爽便利的Windows游戏窗口
  • C++:最强大的.NET语言之可访问性
  • C++:最强大的.NET语言之装箱
  • C++:最强大的.NET语言之内存与资源
  • C++:最强大的.NET语言之对象构造
  • Visual C++2005中开发自定义绘图控件
  • C++/CLI程序进程之间的通讯
 
 

图文教程


  • Windows抢了谁的饭碗 非主流操作系统To

  • 地球还是火星 平常心看“非主流”

  • 综合运用Office 2007批量制作奖状

  • 没有系统盘如何才能修复受损系统?

  • 巧妙运用Excel中边界的附加功能!
 
 
赞 助 商
 
 
VC++2005快速构建安全的应用程序
  • 来源:e股脑
  • 点击次数:
  • 更新时间:2007-8-9
{

std::cout << numbers.at(index) << std::endl;

}

PrintAll函数使用了下标操作符,因为索引由函数控制,并且可以确认是安全的。另一方面,PrintN函数不能保证索引的有效性,所以它使用了更安全的"at"方法来代替。当然,并不是所有的容器的存取操作都象这么简洁明了。

在保证C++标准库的安全特性的同时,Visual C++2005继续坚持并在很多情况下改进了C++标准库的运行特性,同时提供了调节C++标准库安全性的特色。一项受人欢迎的改进是在调试版本中添加了范围检查,这对你的发行版本性能并不构成影响。但这确实帮助你在调试阶段捕获越界错误,甚至是使用传统上不安全的下标操作符的代码。

不安全的函数,象vector的下标操作算子,和其他的函数,象它的front函数,如果不恰当的调用,通常会导致不明确的行为。如果你幸运的话,它将很快导致一个存取冲突,这将使你的应用程序崩溃。如果你不那么走运的话,它可能默默地持续运转并导致不可预知的副效应,这将破坏数据并可能被进攻者利用。为了保护你的发行版本的应用程序,Visual C++2005引入了_SECURE_SCL符号,用来给那些非安全的函数添加运行时检查。象下面的代码那样在你的应用程序中简单地定义这个符号可以添加额外的实时检查并阻止不确切的行为。

#define _SECURE_SCL 1

紧记定义这个符号对你的程序冲击很大,大量的合法的,但是具有潜在非安全的操作将在编译时将无法通过,以避免在运行时出现潜在BUG。思考下面的使用Copy运算的例子:

std::copy(first, last, destination);

其中,first和last是定义拷贝范围的迭代参数,destination是输出迭代参数,指示了目标缓冲区的位置,这个位置用来拷贝范围之内的第一个元素。这里有一个危险是destination所对应的目标缓冲区或容器不足够大,无法容纳所要拷贝的元素。如果Destination是一个需要安全检查的迭代参数,类似的错误将被捕获。但是,这仅仅是一个假设。如果destination是一个简单的指针,将无法保证copy运算函数正确运转。这时当然会想到_SECURE_SCL符号来避免这一问题,这种情况下,代码甚至是不能编译,以此避免任何可能的运行时错误。就象你想象的那样,这将需要重写更完美有效的代码。所以,这是一个更好的理由支持C++标准库容器,避免使用C类型数组。

五、编译器的安全特点

虽然对于Visual C++2005来说并不是全新的,但大量编译器特色仍然需要了解。与以前版本的显著区别是编译器的安全检查当前默认情况下是打开的,让我们来看一下编译器的特点及在某些情况下它们是如何阻止在某些情况下受到攻击。

Visual C++编译器很久以前就开始提供严格的运行时安全检查选项,包括栈校验,下溢和上溢检查以及未初始化变量的识别。这些运行时检查由编译器的/RTC选项来控制。虽然在早期的发展中捕获错误非常有用,但是对于发布版本性能上的损失却是不能接受的。微软的Visual C++.NET引入了/GS编译开关,对于发行版本来说它添加了有限的运行时安全检查。/GS开关在编译开关中插入代码,通过检测函数的栈数据来检测通常基于栈的缓冲溢出。如果发现问题,应用程序将被终止。为了减少运行时检查对性能的影响,编译器辨别哪个函数易于攻击并且仅针对这些函数来进行安全检查。安全检查涉及到在函数的栈框架上增加一个cookie,在缓冲溢出的情况下它将被重写。函数指令的前后都添加了汇编指令。在函数执行以前,源自cookie模块的函数cookie先执行计算。当函数结束但在栈空间被收回前,cookie的栈拷贝被检索以判断它是否被更改。如果cookie未被更改,函数结束并继续执行程序的下一步,如果cookie被更改了,一个安全错误句柄将被调用,它将结束应用程序。


为了在Visual C++ 2005发布版本中控制这些编译选项,打开工程的属性页,单击C/C++标签,在代码发生属性页中,你将发现两个属性对应于我刚刚描述的特点。Basic Runtime Checks属性对应于开发时/RTC编译选项,在编译版本中应设置为"BOTH"。Buffer Security Check属性相当于编译器的/GS选项,对于发布版本应设置为"YES"。

对于使用Visual C++ 2005的开发人员来说,这些编译特点在默认情况下打开,这意味着你可以确信编译器正在尽其可能阻止你代码中的漏洞。然而,这并不意味着我们可以完全不关心安全问题。开发人员需要继续为正确的代码而努力,并且要考虑各种不同的、可能发生的安全威胁。编译器仅仅可以阻止部分类型的错误发生。

要牢记这些编译器提供的特殊的安全检查仅适用于本地代码,幸运的是,托管代码很少犯此类的错误。这里甚至于有更好的消息,Visual C++ 2005引进了C++/CLI设计语言,它提供了.NET框架下最强有力的开发语言。

六、新的C++编程语言

Visual C++ 2005发布版本提供了C++/CLI设计语言的一流的实现。C++/CLI是为.NET设计的系统编程语言。相对于其他语言来说,它在创建和使用.NET模块和汇编上有更多的控制。C++/CLI对于C++开发人员来说更精细和自然,无论你是否熟悉C++或.NET框架,你将发现使用C++书写托管代码是对ANSI C++自然文雅的扩展,学习起来非常容易。

对于开发应用程序来说,有许多强制性的原因让你来选择托管代码而不是本地C++。两个最重要的原因是安全性和效率。通用运行时语言(CLR)给你的代码提供了一个安全的运行环境。作为一个程序开发人员,你不需要关心缓冲区溢出及因为你在使用前未初始化变量等问题。安全问题没有完全消失,但是使用托管可以避免通常发生的一些错误。

另外一个使用托管的原因是.NET框架下丰富的类库。虽然标准C++库更适合于C++类型编程,但是.NET框架包含了一个功能强大的函数库,这是标准C++库所无法比拟的。.NET框架包括很多有用的集合类、一个强大的数据操作库、执行很多流行的通讯协议的类,从SOCKETS到HTTP和网络服务等等。虽然本地C++程序开发人员可以以各种形似使用这些服务,但通过使用.NET框架获取的生产力主要因为它的统一性和连贯性。无论你是用System::Net::Sockets还是用System::Web名字空间,你将面对同样的类型,描述广泛应用的概念,例如流和字符串。这是.NET框架具有开发高效率的最主要的原因。这让程序人员更快速地书写更强有力的应用程序,同时代码更可靠。

Visual C++ 2005自然地准许你在一个工程中混合本地与托管代码,你可以继续使用已经存在的本地函数及类的同时,开始使用越来越多的.NET框架下的类库,甚至是写你的托管类型。你可以将你的托管类型定义为一个引用类型或一个值类型,虽然Visual C++编译器允许你为了方面选择使用栈语法或是为了控制管理资源使用通常的作用域规则,但值类型在栈上而引用类型位于CLR的托管堆上。

通过在你定义的class 和 struct 前添加ref来形成一个关键词,定义了一个引用类型。获取和释放资源按通常的方式完成,通过使用构造和析构函数,正如这里说明的:


ref class Connection

{

public: Connection(String^ server)

{

Server = server;

Console::WriteLine("Aquiring connection to server.");

}

~Connection()

{

Console::WriteLine("Disconnecting from server.");

}

property String^ Server;

};

编译器负责Connection引用类型的IDisposable接口的实现,所以使用类似C#、Visual Basic.NET的开发人员可以使用任何对他们可用的资源管理结构。对于C++开发人员,有着与以前一样的选择。为了简化资源管理,并书写"异常"安全代码,你可以简单地在栈上声明一个Connection对象。当一个对象超过其作用范围后,执行Dispose方法的析构函数将被调用。下面是一个例子:

void UseStackConnection()

{

Connection connection("sample.kennyandkarin.com");

Console::WriteLine("Connection to {0} established!",

connection.Server);

}

这个例子中,通过在函数返回调用前调用析构函数来关闭这个Connection,这正如你在C++希望的那样。如果你希望自己控制对象的生命期,仅仅需要使用gcnew这个关键词来获取connection对象的句柄。这个指针可以看作通常的指针(不含有通常的缺陷),并且这个对象的析构函数可以简单地通过delete操作来调用。这个例子代码如下 :

void UseHeapConnection()

{

Connection^ connection = gcnew Connection("sample.kennyandkarin.com");

try

{

Console::WriteLine("Connection to {0} established!",

connection->Server);

}

finally

{

delete connection;

}

}

正如你所看到的,从本地C++到托管代码,Visua

上一页  1 2 3 下一页
  • 上一篇教程: 完美的C++:C++/CLI
  • 下一篇教程: VC++.NET下GDI+编程之GDI+简介
  •  

    关于本站 | 广告联系 | 版权声明 | 使用帮助

    Copyright © 2004-2008 www.egunao.com All rights reserved.