简体   繁体   中英

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

I start with an integer array test[] which represents a set of images. The first two elements of test[] are the height and width of the first image. The following four (height*width) elements are pixel values. The next six represent the next image and so on.

My goal is to access the images through image objects without duplicating anything in the test[] array. I try to do this via 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 uses the cursor variable to store the start index of the next image. it calls Image::import to read that data into an image object. The data for that particular image should start at the address &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;
    }
}

Within image::import , I get a bad access by attempting to read data[0] . According to the debugger, data[] points to the correct value of 2, but EXC_BAD_ACCESS is thrown anyway when I attempt to get that value via data[0] .

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

I would very much appreciate an explaination of what I am doing wrong. I would equally appreciate suggestions for how to achive my goal without pointer arithmetic.

Thank You!

My guess would be that during the optimization phase the compiler rearranges your loop to

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;
}

And since you defined NUM_SRC_IMAGES too large you are reading past the end of test.

BTW, you should also think about using STL like iterator style and then call set.import(begin(test), end(test)); By abstracting from the underlying type you could read data from any container. And you can check against the end so you never read past the end.

With the limited information in the question, I can suggest the following:

  1. try changing import to be ImageSet::import(const int* data, size_t size) or... preferably, ImageSet::import(const int (&data[18])) - this allows for a clear reference as opposed to a data[] which can be optimized away under some circumstances. The latter also explicitly specifies to your fellow devs that it is an array reference (as opposed to a pointer). Same for Image::import .

  2. In Image::import print out the value of data (ie &data[0] ) - this will let you know if the address is valid.

  3. at the end of the loop in ImageSet::import print out the value of cursor .

My guess is in the third loop or so, the value of cursor grows too large, greater than 18. I don't know what your intention is... but that cursor += 3 + 4*2 logic (as an example) looks real suspicious.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM