VS2013 0xCCCCCCCCC 读取字符串的字符时出错



问题描述

在一个函数调用中,使用二级指针作为函数参数,传递一个字符串指针数组,但是在访问的时候,却出现了运行时错误,具体表现为“0xCCCCCCCC 读取字符串的字符时出错”。
这里写图片描述
第一反应是字符串忘记初始化了,但是一检查不对,我初始化了啊。怎么会出现这种问题,然后通过单步调试发现是传值的二级指针指向的指针数组访问越界了,代码片段如下——

while ((string = *strings++) != NULL) {

        while (*string != '\0')  {
            if (*string++ == ‘a’)//出错的地方,此处string = 0xcccccccc,读取字符串字符时错误
                ...
        }
    }

VS认为越界的字符串指针元素是未初始化的,所以会执行一个默认的初始化,在执行*strings++ 循环判定的时候,越界的元素内容为0xcccccccc,而不是NULL ,所以判断语句无效,访问了无法访问的内存。

那么在判断的时候,数组的边界应该以数组元素的数量为界,而不是NULL 值。

相关知识点的补充

0xcccccccc : Used by Microsoft’s C++ debugging runtime library to mark uninitialised stack memory
0xcdcdcdcd : Used by Microsoft’s C++ debugging runtime library to mark uninitialised heap memory
0xfeeefeee : Used by Microsoft’s HeapFree() to mark freed heap memory

对于0xcccccccc和0xcdcdcdcd,在 Debug 模式下,VC 会把未初始化的栈内存上的指针全部填成 0xcccccccc ,当字符串看就是 “烫烫烫烫……”。会把未初始化的堆内存上的指针全部填成 0xcdcdcdcd,当字符串看就是 “屯屯屯屯……”。

那么调试器为什么要这么做呢?VC的DEBUG版会把未初始化的指针自动初始化为0xcccccccc0xcdcdcdcd,而不是就让取随机值,那是为了方便我们调试程序,如果野指针的初值不确定,那么每次调试同一个程序就可能出现不一样的结果,比如这次程序崩掉,下次却能正常运行,这样显然对我们解bug是非常不利的,所以自动初始化的目的是为了让我们一眼就能确定我们使用了未初始化的野指针了(其实我还是觉得初始化为NULL比较痛快)。

对于0xfeeefeee,是用来标记堆上已经释放掉的内存。注意,如果指针指向的内存被释放了,变量变量本身的地址如未做改动,还是之前指向的内存的地址。如果该指针是一个类的指针,并且类中包含有指针变量,则内存被释放后(对于C++类,通常是执行delete操作),类中的指针变量就会被赋值为0xfeeefeee。如果早调试代码过程中,发现有值为0xfeeefeee的指针,就说明对应的内存被释放掉了,我们的代码已经出问题了。

这是VS特有的机制,在其他编译器上可能会把指针初始化为NULL。

猜你喜欢

转载自blog.csdn.net/cv_jason/article/details/80210601
今日推荐