size_t 专门设计用于表示大小,因此使用它更安全,不太可能发生溢出。...举个例子: size_t a = 10; 和 int a = 10; 在C语言中有几个关键的区别: 类型: size_t a = 10; 声明了一个 size_t 类型的变量 a 并初始化为10。...size_t 是一个无符号整数类型,通常用于表示对象的大小或数组的索引。 int a = 10; 声明了一个 int 类型的变量 a 并初始化为10。...打印: 使用 printf 打印 size_t 类型的值时,应该使用 %zu 格式化字符串。 使用 printf 打印 int 类型的值时,应该使用 %d 或 %i 格式化字符串。...在大多数情况下,如果你只是需要一个能够存储整数值的变量,并且不关心它是否有符号,那么使用 int 是可以的。
2、导致漏洞的几种整数误操作 一般说来,主要有三类整数操作可以导致安全性漏洞,下面列出每类的典型例子:2.1.无符号整数的下溢和上溢 无符号整数的下溢问题是由于无符号整数不能识别负数所导致的。...无符号整数的上溢问题也不难理解,示例代码如下:BOOL fun(char *s1,size_t len1, char *s2,size_t len2){if(len1 + len2 + 1 > 1024...len 参数,但是在之前的数据边界检测使用了有符号整数。...如果整数溢出发生,之后的所有相关操作的结果都将发生变化。与缓冲区溢出不同的是,整数溢出发生时不会马上发生异常,即使程序执行结果与预期的不同,也很不容易发现问题所在。...而无符号整数的下溢和上溢,符号的问题等都可以导致安全性漏洞、我正在参与2023腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!
本文首发于哈希1024社区: https://hash1024.org/topics/97 算术运算的上溢/下溢 和绝大多数编程语言一样,以太坊虚拟机(EVM)中的整数类型是有一定的范围的。...漏洞描述 当某个操作把超出变量数据类型范围的数值写入变量时,则会发生上溢出或者下溢出。在大学里计算机组成原理的课程里面应该有相关的内容。...例如,从一个值为 0、类型为 uint8(8位的无符号整数,即只有正数)的变量减1,将得到数值 255,这称为下溢。...可以使用下溢来绕过第[13]行上的 require 语句。假设有个没有余额的用户,他可使用任何非零 _value 调用 transfer() 函数,并通过第[13]行的 require 语句。...预防技术 防止上溢/下溢漏洞的传统技术是使用或建立标准数学运算的替代数学库;加法,减法和乘法(除法除外,因为它不会导致上溢/下溢,EVM会在除以 0 时回滚)。
对于无符号整数 u32 来说,这种下溢会导致结果变成一个非常大的数,因为 u32 不能表示负数。使用 saturating_sub 后,当减法结果为负时,它会返回 0(即 u32 能表示的最小值)。...和普通的减法操作相比,当发生溢出时,它会“包裹”到类型的最大或最小值,而不是引发溢出错误或产生未定义行为。...与直接减法相比: 直接减法:在 Rust 中,直接使用 - 运算符进行减法时,如果在“调试”模式下发生溢出,程序会触发 panic(崩溃)。...使用 wrapping_sub 后,结果会从 0 下溢到 255,而不是引发 panic。...总结一下, saturating_加减乘除和wrapping_加减乘除 都是提供了一种明确和安全的方式来处理可能的溢出情况,确保即使在溢出发生时,程序行为也是可预测和一致的。
C 语言风格来输出 值得注意的是: 注意变量声明的顺序要和初始化列表一致,也要注意变量初始化顺序对另一个变量的影响;=运算符重载:自我赋值是指对象在赋值时被赋值给自己,例如 s1 = s1,在这种情况下...+1 是为了给 '\0' 留位置,capacity 也表示的是有效字符的容量,同时要记得释放原来指向的不使用的空间 push_back 函数 reserve 时要判断下是因为扩容是 *2 ,避免空间为...size_t 类型的 end 作为索引来遍历字符串,size_t 是无符号整数类型。...当 end 递减到 0 后再进行 --end 操作时,会发生无符号整数溢出,end 的值会变成 size_t 类型所能表示的最大值,这个值恰好和 npos(被初始化为 -1 转换后的 size_t 最大值...'\0' char buff[128] = { '\0' }; // 定义一个索引变量 i 用于记录 buff 数组当前存储字符的位置,初始化为 0 int i = 0; // 循环处理连续的空格和换行符
整数溢出和下溢: 当数学运算的结果超出整数类型所能表示的范围时,会导致数值错误地回绕,这可以被攻击者利用来获取额外的代币或资源。 溢出示例 假设我们有一个智能合约,它接收用户存款并存储在一个变量中。...下溢通常发生在减法操作中,如果从一个较小的数中减去一个较大的数,结果将低于最小整数值(对于无符号整数,最小值是0),从而导致下溢。...在无符号整数中,下溢实际上会导致值从0回绕到最大值,但这通常不是预期的行为,因此仍然被视为错误。...// 假设balance为0 balance = 0; // 尝试取出任何正数都会导致下溢 withdraw(1); // 此时,balance将变成uint256的最大值 解决方案 为了避免整数溢出和下溢...,Solidity提供了安全数学库SafeMath,它包含了检查溢出和下溢的整数运算函数。
溢出原理 计算机中整数变量有上下界,如果在算术运算中出现越界,即超出整数类型的最大表示范围,数字便会如表盘上的时针从12到1一般,由一个极大值变为一个极小值或直接归零,此类越界的情形在传统的软件程序中很常见...下溢增持(CVE-2018-11687) 类型描述:管理员在特定条件下,通过调用合约中有漏洞的发币函数制造下溢,从而实现对自身账户余额的任意增加。 ...当管理员余额本身少于2000 * 108时,减法计算结果为负值,解释为无符号整数即一个极大值。...将会发生下溢,变成一个极大的值,下面在remix中演示操作一下: 编译合约 2.png 部署合约 3.png 下溢操作 调用distribute函数传入地址数组: ["0x14723a09acff6d2a60dcdf7aa4aff308fddc160c...因为你永远都不会发生两个数值相加超过uint256的情况,但是在这中情况下你就应该将目光放到“乘法溢出”或“减法下溢”的问题上来进行查找,审计是否真的不存在“整型溢出”问题。
引用在定义时必须初始化 2. 一个变量可以有多个引用 3....引用在定义时必须初始化,指针没有要求 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体 没有NULL引用,但有NULL指针 在sizeof中含义不同:引用结果为引用类型的大小...auto定义变量时必须对其进行初始化 return 0; } 【注意】 使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto 的实际类型。...为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法 4. auto在实际中最常见的优势用法就是跟以后会讲到的C++11提供的新式for循环,还有 lambda表达式等进行配合使用...(关于迭代器这个问题,以后会讲,现在提一下,没办法 讲清楚,现在大家了解一下就可以了) 五、指针空值nullptr(C++11) 5.1 C++98中的指针空值 在良好的C/C++编程习惯中,声明一个变量时最好给该变量一个合适的初始值
tmp对象会被销毁自动调用析构函数,则释放野指针所指向的空间就会发生越界访问,程序就会崩溃,所以最好的解决办法就是利用初始化列表先将this的成员变量初始化一下,对于有资源的_pstr我们利用nullptr...end是size_t定义的,那么-1会被认为是无符号整数,进行隐式类型转换,由于-1的补码是全1,被当作无符号整数的话,它的原码就被看作是全1了,那就是四十二亿九千万大小,程序会陷入死循环。...// (1)还是用下面强转的方式简单 int end = _size;//用int就是为了防止end为-1时,循环还能继续进行从而发生死循环 while (end >= (int)pos)//这样的代码是可以支持头插的...char* _pstr; size_t _size;//理论上不可能为负数,所以我们用size_t类型进行定义 size_t _capacity; //如果在调用构造函数的时候没有显示传参初始化成员变量...,则成员变量会利用C++11的缺省值在构造函数的初始化列表进行初始化 const static size_t npos = -1; //静态成员变量在类中声明,定义必须在类外面,因为它属于整个类
在这种情况下,回调函数就派上了用场。...使用方式不同:普通指针通过解引用操作符 * 来访问变量的值,而函数指针通过调用操作符 () 来调用函数。...函数指针必须被正确初始化,否则调用它时可能会导致未定义行为。...函数指针可以通过以下方式初始化: 直接赋值:将函数的地址赋值给函数指针。 void (*func_ptr)(int) = func1; 使用取地址操作符:使用 & 操作符获取函数的地址。...事件驱动编程是一种编程范式,它允许程序在事件发生时执行特定的代码。回调函数通常用于处理事件,例如用户输入、定时器事件或网络事件。
漏洞危害:用户提币之后,无法得到对应数额的ETH; 漏洞原理:sellPrice被修改为精心构造的大数后,可导致amount sellPrice的结果大于整数变量(uint256)最大值,发生整数溢出...下溢增持(CVE-2018-11687) 类型描述:管理员在特定条件下,通过调用合约中有漏洞的发币函数制造下溢,从而实现对自身账户余额的任意增加。...当管理员余额本身少于2000 * 108时,减法计算结果为负值,解释为无符号整数即一个极大值。...,而且也没有判断合约的owner是否有足够的代币,直接一个循环对owner进行减法处理,这里如果转出的代币总量大于owner账户余额,那么balance[owner]将会发生下溢,变成一个极大的值,下面在...因为你永远都不会发生两个数值相加超过uint256的情况,但是在这中情况下你就应该将目光放到“乘法溢出”或“减法下溢”的问题上来进行查找,审计是否真的不存在“整型溢出”问题。
图1-3 整数2的二进制编码存储方式 虽然在计算机中整数是以二进制编码方式进行存储的,但为了便于表达,有时候又会用十六进制编码方式表示(例如,在32位操作系统下,整数2的十六进制编码方式为0x00000002...最后还需要说明的是,当类型修饰符被自身使用时(即它不在基本类型之前时),假定其为int型。也就是说,表1-4的两种类型是等效的。 表1-4 等效的整数类型 ?...size_t类型的变量大小足以保证存储内存中对象的大小,任何表示对象长度的变量,包括作为大小、索引、循环计数和长度的整数值,都可以声明为size_t类型。...因此,当n的值为0 时,执行循环n次,代码如预期一样正常运行;但当n的值为int_max变量i的增值超过int_max时,i的值将是从int_min... 因此,为了避免发生这种潜在性的错误,应该将变量i也声明成size_t类型,如代码清单1-4所示。
#include #include "MyHeader.hpp" 初始化成员变量 ...使用成员初始化列表。.... // 除非有明确的理由,否则优先使用{}初始化,而不是=。 忘记初始化成员会导致未定义行为错误,而这些错误通常很难发现。 如果成员变量在初始化后不会更改,则将其标记为const。...为标准库特性使用正确的整数类型 标准库通常使用std::size_t来处理与尺寸相关的内容,size_t的大小由实现定义。 一般来说,使用auto可以避免大部分问题。...请确保使用正确的整数类型,并与C++标准库保持一致,否则有可能在当前使用的平台上不会发出警告,但如果切换到其他平台,可能会发出警告。 注意,在对无符号数执行某些操作时,可能会导致整数下溢。...不要混用tab和空格 某些编辑器喜欢在默认情况下使用tab和空格的混合缩进,这使得没有使用完全相同的tab缩进设置的人很难阅读代码。请配置好编辑器,确保不会发生这种情况。
成员变量 结合我们的使用,我们可以发现string事实上就是一个字符串,但是里面添加了统计容量和字节大小的两个成员变量~ 因此,私有成员我们可以像下面这样: class my_string//与库里面的进行区分...1、使用常量字符串进行初始化~ 像以前,我们初始化会建议在初始化列表进行初始化,这一次为了代码更加简便,我们首先使用初始化列表初始化string的长度~剩下的就可以使用已经初始化的长度在函数体里面进行初始化...2.使用n个字符进行初始化,那么这里就需要两个参数,一个是我们希望的字符长度,一个是初始化的字符~这里的初始化我们就可以完全使用初始化列表进行初始化,因为字符串的长度是已经知道的~ my_string...当使用赋值运算符(=)将一个对象的值赋给另一个同类型的已存在对象时,会调用重载的赋值运算符。 避免自赋值: 在实现赋值运算符重载时,必须考虑自赋值问题,即对象赋值给自己的情况。...~其他情况下,容量不会发生变化~ void my_string::reserve(size_t n) { if (n > _capacity)//修改容量比原来的大就进行扩容 { char* tmp
而如果改成引用类型,就不会发生上述转换。...所以使用范围for语句处理多维数组的时候,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型 #include #include #include使用下标运算符 for (size_t row = 0; row < 3; row++) for (size_t col = 0; col < 4; col++)...cout << ia[row][col] << endl; cout << endl; //使用普通for语句,使用指针 int(*p)[4] = ia; //p指向含有4个整数的数组...5.为什么需要对序列中的元素执行写操作的时候,循环变量必须声明成引用类型?
Dos问题 [1] 循环消耗问题 在合约中,不推荐使用太大次的循环 在以太坊中,每一笔交易都会消耗一定量的gas,而实际消耗量是由交易的复杂度决定的,循环次数越大,交易的复杂度越高,当超过允许的最大gas...上述代码如果控制函数调用,那么就可以构造巨大循环消耗gas,造成Dos问题 3、编码安全问题 (1) 溢出问题 [1] 算术溢出 在调用加减乘除时,应使用safeMath库来替代,否则容易导致算数上下溢...=address(0))验证,有效避免用户误操作或未知错误导致的不必要的损失 由于EVM在编译合约代码时初始化的地址为0,如果开发者在代码中初始化了某个address变量,但未赋予初值,或用户在发起某种操作时...在智能合约中,所有的整数除法都会向下取整到最接近的整数,当我们需要更高的精度时,我们需要使用乘数来加大这个数字。...而存在storage(存储器)和memory(内存)是两个不同的概念,solidity允许指针指向一个未初始化的引用,而未初始化的局部stroage会导致变量指向其他储存变量,导致变量覆盖,甚至其他更严重的后果
默认情况下,引用和变量在是不可变的——帮助开发人员遵循最小特权的安全原则,仅当他们真正希望引用或变量可变时,才将其标记为可变。尽管 C++ 有一定的特点,但它往往不经常使用,也不一致。...初始化赋值——要求在使用前,初始化所有变量。未初始化的内存漏洞一直是 Android 平台上 3-5% 比例的安全漏洞的根本原因。...Rust 要求每个变量在使用前,都初始化为其类型的合法成员,避免了无意中初始化为不安全值的问题。...更安全的整数处理——默认情况下,对 Rust 调试和构建,启用溢位清理(overflow sanitization),鼓励程序员指定一个 wrapping_add(如果他们真的希望溢位计算),或 saturating_add...我们打算为 Android 平台中的所有构建,都启用溢位清理。此外,所有整数类型转换,都是显式强制转换:当分配给变量或尝试对其他类型执行算术运算时,开发人员不能在函数调用期间,意外地强制转换。
对于有符号整数溢出,计算机系统使用的处理方式可能有多种,其中常见的有两种方式:单纯截断溢出:当结果超出最大可表示的有符号整数时,系统将结果截断为最大可表示的有符号整数,即结果会变成一个非常大的正数或非常小的负数...二进制补码溢出:计算机系统中使用补码表示有符号整数,因此,当溢出发生时,系统会将结果的高位截断,保留低位作为最终结果。...因此,在进行整数运算时,程序员需要注意并进行适当的溢出检查和处理。对于浮点数的溢出处理计算机系统处理浮点数溢出和下溢的情况主要依赖于浮点数的表示形式和数值范围的限制。...浮点数下溢当一个浮点数小于它所能表示的最小非零值(即接近于0),发生下溢。根据浮点数的表示形式,系统会将数值设置为接近于0的特殊值,通常是最小非规约数或0。...计算机系统处理浮点数溢出和下溢的策略如下:当进行算术运算时,系统会检查是否溢出或下溢,并且根据标准规定的行为来处理,通常会将结果设置为特殊值或触发异常。
从使用角度,虚函数主要用于信息不全的情况下,使子类重写的函数能得到对应的调用。构造函数本身就是要初始化对象,所以用虚函数没有意义。...在 C++ 中,这三种情况下拷贝构造函数会被使用: 一个对象以值传递的形式传入函数内。 一个对象以值传递的形式从函数返回。 一个对象通过另一个对象初始化。 优点:可以很容易的复制对象。...<< a << endl; cout << ::a << endl; return 0; } 全局变量的初始化的顺序 同一文件中的全局变量按照声明顺序,不同文件之间的全局变量初始化顺序不确定。...如果要保证初始化次序的话,需要通过在函数使用静态局部变量并返回来实现。...通过位运算实现加减乘除取模 加法操作 对于每一位而言,在不考虑进位的情况下,可以得到 0+0 = 0\\ 0+1 = 1\\ 1+0 = 1\\ 1+1 = 0 显然,上面的情况符合 异或 操作且只有第四种情况发生了进位
领取专属 10元无门槛券
手把手带您无忧上云