C++ Gurus, Can You Explain This?

SkulkBaitSkulkBait Join Date: 2003-02-11 Member: 13423Members
edited April 2004 in Off-Topic
<div class="IPBDescription">really, what am I missing about this...</div> So I was working on this program, which was crashing when I tried to read from a particular array, lets call it TM. Heres what the call looked like:

<!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
unsigned char *TM;
...
TM = new unsigned char[size];
...
if(fread(&TM, sizeof(unsigned char), size, pFile) != size)
{
  //do failure stuff
}
...
unsigned char x = TM[index]
<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

And it would crash on that last line. It was easy to fix, once I found the error (&TM should just be TM, boy did I smack myself when I noticed it), which took a while since there is obviously more code than I'm showing here and everything regarding access to TM worked until I tried to read from it. What I don't get is why the fread succeded even though I gave it an invalid pointer. Any ideas?

Comments

  • SkulkBaitSkulkBait Join Date: 2003-02-11 Member: 13423Members
    I got annother one too, if anyone ever gets around to reading this:

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    unsigned char *p;
    *p = 0;

    fwrite(p, sizeof(unsigned char), size, pFile);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    size in this case is a fairly large number, when the resulting file is examined with a hex editor, one can clearly see that it did not generate all 0x00s as intended. Any ideas?
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    edited April 2004
    About your first question: C doesn't give a damn what your pointers are pointing to when you try to access them, it just lets you do it. The operating system, however, <i>does</i> give a damn. Well, it does if it's any good. Any modern OS.

    TM is a pointer, so the value it contains is a memory address. Since a pointer is a variable, it's also stored somewhere, and therefore has an address itself. <span style='font-family:Courier'>&TM</span> is the address of the pointer. That's still a memory address. So you're overwriting your pointer, and because you're writing more than pointer-sized data you'll start corrupting whatever's after that pointer until you get a segmentation violation, which is your OS protecting other processes from your stuff-ups, and the reason why it crashes.

    About your second question:
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->fwrite(p, sizeof(unsigned char), size, pFile);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    size is not how many times to write. It's how many elements to write. Think about that for a second.

    *p == 0 == p[0], right? What does p[1] equal? God knows. Whatever values were left in the memory from last time it was written to. So if you're writing all the way up to, say, p[256] then you're writing one zero (which you put there, in *p = 0) and then 255 god-knows-whats.
  • CreepieCreepie Join Date: 2003-02-19 Member: 13734Members
    edited April 2004
    size_t fread(void* buffer, size_t size, size_t count, FILE* stream);
    size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream );

    The size of <i>buffer</i> must be (<i>size</i> * <i>count</i>) bytes. For both functions.

    In answer to your first question, fread will simply write to whatever happens to be at <i>buffer</i>. C makes no distinction between valid and invalid addresses. So, in your <i>&TM</i> case, fread will trash whatever is at <i>&TM</i>. The end result is that fread will either continue obliviously, or crash your program. Or your program could crash in the future because the memory fread has overwritten has now been read by something further in the program. Evil.

    The second question, refer to my original point about the size of <i>buffer</i>. Now look at the size of your buffer <i>p</i>. Some code for writing 0s to <i>stream</i>:

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    unsigned char* p = new unsigned char[size];
    memset(p, 0, size);
    fwrite(p, sizeof(unsigned char), size, pFile);
    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    A quick point about your first code:

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    if(fread(&TM, sizeof(unsigned char), size, pFile) != size)
    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    fread can return less than size when it reaches EOF. In this case, use feof or ferror to determine if you have a file error, or that you've reached EOF.
Sign In or Register to comment.