数组下标越界错误

CSDN的博客是我很早以前就开通的,可是一直没有把这个资源有效利用起来。虽然写博客的想法很早以前就有,但一直没有实施。一方面担心我自己水平不够,想着还是不要丢人现眼了;另一方面就是懒,各种借口加起来本质就是懒。但最近我发现我曾经做过的大大小小的项目还有写的各种函数算法都没有进行一个系统的总结,需要用到的时候总要浪费时间查找,没有有效利用我曾经的经验;此外,我在敲代码的经历中犯过无数愚蠢的错误,而且今后还会犯更多的错误。为了以后不犯同类型错误,我打算记录下来引以为戒。今天我在这里写下第一篇博客,希望能有个好的开端。

【问题发现】

我在通过C++进行DES加密算法实现的时候出现了差错,检查调用堆栈发现是实现F变换的时候出的问题,于是进行了进一步检查,得出的结果是在进行E变换扩展之后,得到的48位数与密钥的异或运算时出了差错,再进行检查,发现是轮密钥的计算有错误。


DES加密算法的F变换示意图

因为我是用数组的形式存储密钥的每个bit的(需要进行位的变换),因而我一个一个位的看,很快,我发现当前密钥的第40位(keys[39])不是0或1,而是一个很大的负数,很明显这是没赋值的数。而且不单单是当前用到的密钥是这样,我计算出的所有密钥第40位都是这样的数。因为输入的密钥没有问题,而计算轮密钥的时候有一个步骤是循环的,所以我断定问题出在那里。


DES加密算法的轮密钥生成示意图

果然,我找到了问题所在。在轮密钥生成的过程中,有一个PC-2变换,这是通过查找PC-2表进行的变换工作。该表第i个位置对应的数字N的意思是,把变换前数据的第N位放到变换后数据的第i位,最后从56位数据变换成一个48位数据。我之前想,这太简单了,于是敲出了以下代码:

<span style="font-family:Courier New;font-size:14px;">for (int i = 0; i < 48; i++)
<span style="white-space: pre;">	</span>out48[i] = in56[PC2[i]];</span>

但实际不是这样。因为数组的计数都是从0开始,而表中数字是从1开始,所以实际使用的时候要么在初始化PC-2表的时候每个数字都减1,要么在进行变换的时候把取得位数减1。而我这两步都没有做,所以当需要取最后一位、即第56位的时候,应该取变换前数据的标号为55的数,但这个程序取得是56,而变换前的数组根本没有这一位,所以最后的结果是那样的了。而根据PC-2表可知,要求取56位的正好位于表中第40个位置。


DES加密算法PC-2表

【问题解决】

所以这次的错误本质上是数组下标越界,是因为我没有注意下标方面的问题导致的。这个问题很好解决,我把代码稍稍进行了修改:

<span style="font-family:Courier New;font-size:14px;">for (int i = 0; i < 48; i++)
	out48[i] = in56[PC2[i]-1];</span>
问题解决。但实际上这个算法有好多地方都用到类似的表,而所有位置我都没有关注下标问题,因为各种原因都顺利通过了编译,要不是因为计算轮密钥的问题我根本没有发现我的代码中隐藏了这么一个愚蠢的错误。之后我也把代码中其他地方的类似错误都改了过来。

【总结】

1、怎样尽可能避免这种错误呢?不知道用enum是否可行。因为进行的是对位的操作,所以我定义了许多数组都只能接受0和1,而我用的数据类型是int。当时使用它是因为顺手,虽然挺浪费空间但我还是没放在心上。之后一直觉得修改优化太麻烦所以没有做,果然这种懒惰性是要不得的

2、不要小看看起来简单或熟悉的东西考虑出现这个错误的更本质原因。如果是其他更复杂的操作,那么我都会仔细推敲多遍,在纸上写写画画计算好了再敲代码,譬如实现S变换的时候;如果是一般使用数组的问题,我习惯性的就从0开始;但因为DES中一般的变换太简单了,都是两行代码就实现,所以专注于其他算法的实现时反而忽略了“表中的数不是从0开始的”这一点。

3、这是一个小问题,修改也就加两个字符的事,但要找到这个错误却花了我好久。如果当初多想想,敲代码时更细心一点,那么是不是结果会更好。虽然说是这么说,实际做的时候总会一不留神让各种错误发生,所以我要做到的是,犯过的这个错误以后绝不再犯

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值