Search code examples
c++pass-by-referencecimg

C++ pass by reference returning junk or in wrong variable


I'm pulling pixel data from an image using the CImg library and placing it in an array in a struct:

int JpgHandle::loadJpg(const char* Name, SImageData & data){

    CImg<unsigned long> src(Name);
    int width = src.width();
    int height = src.height();
    unsigned long * pixels = new unsigned long [width*height];
    for (int r = 0; r < height; r++){
        for (int c = 0; c < width; c++){
            unsigned long pixel = (src(c,r,0,2) ) |
                                  (src(c,r,0,1) <<  8) |
                                  (src(c,r,0,0) << 16);
            *(pixels++) = pixel;
        }
    }

    data.pData = pixels;
    data.lWidth = (long) width;
    data.lHeight = (long) height;
    data.lStride = (long) width;

    return 1;
}

SImageData is defined thus:

struct SImageData {
    unsigned long *pData;
    long lWidth;
    long lHeight;
    long lStride;

    SImageData() : pData(NULL), lWidth(0), lHeight(0), lStride(0) {}
};

When I call loadJpg from main like this:

JpgHandle handler;
SImageData data1;

handler.loadJpg(argv[1], data1);

cout << "data1: ";
for(int i = 0; i < 10; i++){
    cout << hex << data1.pData[i] << ", ";
}
cout << "\n";

It returns junk:

data1: 0, 1eff1, 7f226014e798, 7f226014e798, 0, 0, 0, 0, 0, 0, 

However, if I do this in main:

JpgHandle handler;
SImageData data1;
SImageData data2;

handler.loadJpg(argv[1], data1);
handler.loadJpg(argv[2], data2);

cout << "data1: ";
for(int i = 0; i < 10; i++){
    cout << hex << data1.pData[i] << ", ";
}
cout << "\n";

cout << "data2: ";
for(int i = 0; i < 10; i++){
    cout << hex << data2.pData[i] << ", ";
}
cout << "\n";

The result is that data1 contains the data from argv[2] and data2 contains junk:

data1: 0, 2011, a0a0a, a0a0a, a0a0a, 90909, 90909, a0a0a, b0b0b, b0b0b, 
data2: 0, 7f0d7d712798, 0, 0, 0, 0, 0, 0, 0, 0, 

What gives?


Solution

  • You should save the pointer to allocated memory into data.pData before you enter the nested loops. The loops increment pixels so it no longer points the the start of the memory block.

    Do you ever call delete[] on data.pData? That should have triggered a fault because it wasn't the same address returned from new[].