static_cast

Started by
11 comments, last by iMalc 19 years, 5 months ago
Does static_cast cause the argument to be converted right there on the spot, or does it only store the cast into the LHS? For example, this code is throwing an access violation error when it gets to the first delete[] statement:

// real_out and im_out are double** arrays

for (int i = 0; i < height; i++)
    for (int j = 0; j < width; j++)
    {
        fftData[k] = static_cast<float>(real_out[j]);
        fftData[k + 1] = static_cast<float>(im_out[j]);
    }

    for (int i = 0; i < MRCHeight; i++)
    {
        delete[] real_out;  <=== ERROR HERE!  ACCESS VIOLATION!
        delete[] im_out;
    }

    delete[] real_out;
    delete[] im_out;


However, if I comment out the static_cast statements, no problems. Is this always the case? For some reason I thought the cast was only applied to a return value...not the actual value itself. If this really is what is causing the problem, what cast should I use to make sure the fftData value is properly assigned as a float?
Advertisement
cant use my hands ;-) .. post deleted


try this instead:

for (int j = 0; j < width; j++)
{
fftData[k] = (float)(real_out[j]);
fftData[k + 1] = (float)(im_out[j]);
}

[Edited by - hoLogramm on November 8, 2004 4:48:57 AM]
Quote:Original post by StonieJ
For some reason I thought the cast was only applied to a return value...not the actual value itself.


That is correct. A cast actually creates a temporary rvalue of the target type. The original lvalue is not modified.
I suspect you are writing past the end of your fftData array, trashing the bookkeeping headers for the real_out and im_out arrays.

i.e. it's the assignment, not the cast which is at fault.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by hoLogramm
try this instead:

for (int j = 0; j < width; j++)
{
fftData[k] = (float)(real_out[j]);
fftData[k + 1] = (float)(im_out[j]);
}


If the jist of your post is that old C casts are preferrable over the new C++ cast operators then I disagree very strongly. The C++ cast operators are much more explicit and you actually have to stop and think a second what kind of cast you really need/want rather than just casting away for the heck of it.
There's almost certainly a bug in that original code because the first nested loops are equivalent to:
for (int i = 0; i < height; i++){	fftData[k] = static_cast<float>(real_out[width - 1]);	fftData[k + 1] = static_cast<float>(im_out[width - 1]);}

The way it is at the moment you just keep overwriting the values width times.

Enigma
no, it doesn't look like you're overwriting values... except for possibly i. Your indentation makes it look like the deletion loop happens inside the first for(i = 0; i < width...). However, I suspect that's just a cut-and-paste artifact.

Is MRCHeight == height ?
what type is real_out to begin with that you would want to cast?
The code posted most certainly does overwrite values for width > 1. If you unroll the inner loop of the first double-loop:
for (int i = 0; i < height; i++){	/* unroll this loop	for (int j = 0; j < width; j++)	{		fftData[k] = static_cast<float>(real_out[j]);		fftData[k + 1] = static_cast<float>(im_out[j]);	}*/	fftData[k] = static_cast<float>(real_out[0]);	fftData[k + 1] = static_cast<float>(im_out[0]);	fftData[k] = static_cast<float>(real_out[1]);	fftData[k + 1] = static_cast<float>(im_out[1]);	fftData[k] = static_cast<float>(real_out[2]);	fftData[k + 1] = static_cast<float>(im_out[2]);	// ...}

k never changes, so the values of fftData[k] and fftData[k + 1] are written multiple times.

Enigma
I agree that using C++ style casts' is almost always preferable to C cast.

Just for the simple fact that you can much easier grep for them. ie finding all static_cast<float>(..) is alot easier to find that (float).

The latter would produce alot of false positives. for things like funciton prototypes and definitions with no parameters.

Cheers
Chris
CheersChris
Crap, perhaps I should have posted the whole algorithm. I left out the k terms because I just got lazy, but I will include them now. Ultimately, this is what I'm trying to do:

1) Read in two arrays of data.
2) Merge them into a single array of data.

Shouldn't be too hard I'd think. Here is the complete, relevant code segment with my error code (i.e. I left out some stuff that simply wasn't vital):

void CEMData::FFT(){    double **real_in = new double*[MRCHeight];    double **im_in = new double*[MRCHeight];    double **real_out = new double*[MRCHeight];    double **im_out = new double*[MRCHeight];    try    {    if (!real_in)        throw Exception("Possibly out of memory.");    if (!im_in)        throw Exception("Possibly out of memory.");    if (!real_out)        throw Exception("Possibly out of memory.");    if (!im_out)        throw Exception("Possibly out of memory.");    for (int i = 0; i < MRCHeight; i++)    {        real_in = new double[MRCWidth];        im_in = new double[MRCWidth];        real_out = new double[MRCWidth];        im_out = new double[MRCWidth];    }    for (int i = 0; i < MRCHeight; i++)    {        if (!real_in || !im_in || !real_out || !im_out)            throw Exception("Possibly out of memory.");    }    // the imaginary input array should be all zeros    for (int i = 0; i < MRCHeight; i++)        ZeroMemory(im_in, sizeof(double) * MRCWidth);    // POPULATE INPUT ARRAYS (not shown)        // do the one-dimensional transform on the rows    for (int i = 0; i < MRCHeight; i++)        fft(MRCWidth, real_in, im_in, real_out, im_out);    // permute the rows and store them in the input variables (since we will be inputting them again)    for (int i = 0; i < MRCHeight; i++)    {        for (int j = 0; j < MRCWidth; j++)        {            real_in[j] = real_out[j];            im_in[j] = im_out[j];        }    }    // do the one-dimensional transform on the rows again (which used to be the columns)    for (int i = 0; i < MRCHeight; i++)        fft(MRCWidth, real_in, im_in, real_out, im_out);    // delete the input data since we're done with it    for (int i = 0; i < MRCHeight; i++)    {        delete[] real_in;        delete[] im_in;    }    delete[] real_in;    delete[] im_in;    // convert the transform data from double to float    // HERE IS WHERE THE PROBLEMS START OCCURRING        fftData = new float *[MRCHeight];    if (!fftData)        throw Exception("Possibly out of memory.");    for (int i = 0; i < MRCHeight; i++)        fftData = new float[MRCWidth];    /* NOTE FOR THE INNER LOOP...YOU ONLY NEED THE FIRST W/2 + 1 COLUMS OF THE DATA...NOT THE ENTIRE WIDTH */    for (int i = 0; i < MRCHeight; i++)    {        int k = 0;        for (int j = 0; j < MRCWidth / 2 + 1; j++)        {            fftData[k] = static_cast<float>(real_out[j]);            fftData[k + 1] = static_cast<float>(im_out[j]);            k += 2;        }    }    // delete the original output data since we're done with it    for (int i = 0; i < MRCHeight; i++)    {        delete[] real_out;  <=== ERROR HERE!!!        delete[] im_out;    }    delete[] real_out;    delete[] im_out;}
Two things that look suspicious:
1.
    for (int i = 0; i < MRCHeight; i++)    {        for (int j = 0; j < MRCWidth; j++)        {            real_in[j] = real_out[j];            im_in[j] = im_out[j];        }    }

This will only work if MRCHeight == MRCWidth otherwise you are reading out of bounds of real_out and im_out.
2.
        int k = 0;        for (int j = 0; j < MRCWidth / 2 + 1; j++)        {            fftData[k] = static_cast<float>(real_out[j]);            fftData[k + 1] = static_cast<float>(im_out[j]);            k += 2;        }

fftData is defined to be an array of size MRCWidth but you are writing ((MRCWidth / 2) + 1) * 2 items to it, or MRCWidth + 2 items, so you are overwriting the bounds of the array.

Enigma

This topic is closed to new replies.

Advertisement