为什么我得到EXC_BAD_ACCESS,即使指针看起来是有效的

Why do I get EXC_BAD_ACCESS even though the pointer appears to be valid?

本文关键字:指针 看起来 有效 ACCESS EXC 为什么 BAD      更新时间:2023-10-16

我从一个整数数组test[]开始,它表示一组图像。CCD_ 2的前两个元素是第一个图像的高度和宽度。以下四个(height*width)元素是像素值。接下来的六个代表下一个图像,依此类推

我的目标是通过图像对象访问图像,而不复制test[]阵列中的任何内容。我尝试通过ImageSet::import来做到这一点。

int main(){
    int test[] = {2,2,1,2,3,4,
                  2,2,4,5,6,7,
                  2,2,9,8,0,9};
    ImageSet set = ImageSet();
    set.import(test); //ImageSet::import
    return 0;
}

ImageSet::import使用光标变量来存储下一个图像的开始索引。它调用CCD_ 7将该数据读取到图像对象中。该特定图像的数据应当从地址&data[cursor]开始。

void ImageSet::import(int data[]){
    int cursor = 0;
    for(int i = 0; i < NUM_SRC_IMAGES; i++){
        int height = data[cursor];
        int width = data[cursor+1];
        source_[i].import(&data[cursor]); //this is Image::import
        cursor += height * width + 2;
    }
}

image::import中,我试图读取data[0],导致访问失败。根据调试器的说法,data[]指向正确的值2,但当我试图通过data[0]获取该值时,无论如何都会抛出EXC_BAD_ACCESS

void Image::import(int data[]){
    height_ = data[0]; //the problem occurs right here
    width_ = data[1];
    matrix_ = &data[2];
}

如果能解释一下我做错了什么,我将不胜感激。对于如何在不使用指针运算的情况下实现目标,我同样非常感谢您的建议。

谢谢!

鉴于问题中的信息有限,我可以提出以下建议:

  1. 尝试将导入更改为ImageSet::import(const int* data, size_t size)或。。。优选地,ImageSet::import(const int (&data[18]))-这允许清晰的参考,而不是在某些情况下可以优化掉的数据[]。后者还明确地向您的开发伙伴指定它是一个数组引用(而不是指针(。与Image::import相同。

  2. Image::import中,打印出data(即&data[0](的值-这将使您知道地址是否有效。

  3. 在循环结束时,在CCD_ 20中打印出CCD_。

我的猜测是,在第三个循环中,test[]2的值变得太大,大于18。我不知道你的意图是什么……但cursor += 3 + 4*2逻辑(作为一个例子(看起来真的很可疑。

我的猜测是,在优化阶段,编译器会将循环重新排列为

for(int i = 0; i < NUM_SRC_IMAGES; i++){
    source_[i].import(&data[cursor]); //this is Image::import
    int height = data[cursor];   // -> would also crash, but you don't see it because import crashes earlier
    int width = data[cursor+1];
    cursor += height * width + 2;
}

由于您定义的NUM_SRC_IMAGES太大,所以您的读数已经过了测试结束。

顺便说一句,您还应该考虑使用类似STL的迭代器样式,然后调用set.import(begin(test), end(test));。通过从底层类型中抽象,您可以从任何容器中读取数据。你可以对照末尾进行检查,这样你就永远不会读过末尾。