debug记录:解答错误并出现较大数字

文章讨论了C++中数组和vector下标越界时,为何不报错且可能产生随机结果的情况。这是由于C++的未定义行为,以及编译器不进行边界检查以优化性能。当访问超出范围的内存时,结果取决于该内存区域的当前值,可能导致异常数值或程序崩溃。使用内存错误检测工具如AddressSanitizer可以帮助检测某些越界访问,但不能完全防止所有问题。
摘要由CSDN通过智能技术生成

示例:leetcode188.买卖股票的最佳时机

最开始手误的一版错误写法

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if(prices.size()==1) return 0;
        vector<vector<int>>dp(prices.size(),vector<int>(2*k+1,0));
        //初始化
        for(int i=1;i<=2*k;i++){
            //此处手误写错,-prices[i]会导致下标越界
            dp[0][i]=(i%2==0)?0:-prices[i];
        }
        //递推
        for(int i=1;i<prices.size();i++){
            for(int j=1;j<=2*k;j++){
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+(j%2==0?prices[i]:-prices[i]));
            }
        }
        //return *max_element(dp[prices.size()-1].begin(),dp[prices.size()-1].end());
        return dp[prices.size()-1][2*k];
    }
};

这个写法运行的时候,遇到下面用例输出了如下结果:
在这里插入图片描述
输入prices的size是3,而k=2的时候2*k=4,也就是说下面这个for循环访问了prices数组不存在的下标prices[4]

for(int i=1;i<=2*k;i++){
   //此处手误写错,-prices[i]会导致下标越界
   dp[0][i]=(i%2==0)?0:-prices[i];
}

但是这种情况并没有报错,只是输出了一个极大的数值1094795580。

本来以为这种情况是vector底层发生了动态扩容,所以并没有报错。但是实际上,vector下标越界而没有报错,并非由于 vector 的动态扩容机制导致的

而是因为,在 C++ 中,访问数组(包括 vector)下标超出其大小时,其行为是未定义的,也就是说,它可能产生任何结果,包括但不限于返回一个随机值、导致程序崩溃等

得到的 1094795590 这个很大的数字,是因为代码访问了 vector 空间之外的内存,那块内存恰好有这个值。这个数值并不取决于 C++ 的版本,而是取决于访问的那块内存中恰好存储的值,这个值是随机的

为什么c++数组下标越界了但是没有报错?

C++ 的数组或者向量在下标访问时,不会进行边界检查,这是因为 C++ 设计哲学中有一条就是"你不需要付出你不用的代价",也就是说,如果每次访问数组或者向量都进行边界检查,那么会带来额外的性能开销,而这部分开销对于绝大多数情况是没有必要的

对于下标访问的数组或者向量,如果下标超过了其大小,那么会进入未定义行为(Undefined Behavior),即任何事情都可能发生。可能是崩溃,可能是返回一个不可预期的值,也可能是毫无表现。在上面的情况下,看到的就是返回了一个看似随机的值。

那么平时编程为什么下标为负数的时候会报错?

平时我们编程的时候,数组下标是负数的时候,C++ 会报错,这其实是因为我们使用的编译器或者环境开启了 AddressSanitizer 这样的内存错误检测工具。AddressSanitizer 通过添加一些运行时检查,可以发现一些内存错误,比如数组越界访问(包括下标为负和下标超过大小)。但是,AddressSanitizer 并不能保证检测所有的数组越界访问,特别是当下标超过数组大小很多时,可能就无法检测到了

总的来说,C++ 并不会在运行时对数组或者向量的下标访问进行边界检查,如果下标超过了其大小,那么会进入未定义行为,即任何事情都可能发生。因此程序员需要自己确保不会发生越界访问。如果需要额外的安全性,可以使用一些工具来检测可能的错误,但是这些工具也不能保证能发现所有的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值