I am doing the task for cs50, I need to restore all the jpg images from the memory card, which are copied from the card to the card.raw file. Below is the working code. But if I declare a variable count below the array, i.e. like this

BYTE jpgBlock[512]; int count = 0; 

The program stops working correctly. Namely, in the while loop after the first pass of the inner loop (when the jpg signature is found and the 1st image is recorded to the end - that is, until the signature of the next picture is found) at the end, the counter increases and the count is 1, going to 2 pass after line

 sprintf(outfile, "%03d.jpg", count); 

the counter is reset, i.e. count becomes 0. Why so? Why it depends on whether count is declared higher or lower than BYTE jpgBlock [512];

 #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <cs50.h> typedef uint8_t BYTE; int main(void) { FILE *inptr = fopen("card.raw", "r"); if (inptr == NULL) { return 1; } int count = 0; BYTE jpgBlock[512]; while(1) { char outfile[7]; sprintf(outfile, "%03d.jpg", count); FILE *outptr = fopen(outfile, "w"); if(outptr == NULL) { return 2; } for (int countFirstBlock = 0; fread(jpgBlock, sizeof(jpgBlock), 1, inptr) == 1; ) { if(jpgBlock[0] == 255 && jpgBlock[1] == 216 && jpgBlock[2] == 255) { ++countFirstBlock; } if(countFirstBlock == 1) { fwrite(jpgBlock, sizeof(jpgBlock), 1, outptr); } if(countFirstBlock == 2) { break; } } fclose(outptr); if(feof(inptr)) { break; } fseek(inptr, -(int)sizeof(jpgBlock), SEEK_CUR); ++count; } fclose(inptr); return 0; } 

    1 answer 1

    The fact is that your

     sprintf(outfile, "%03d.jpg", count); 

    crashes out of buffer

     char outfile[7]; 

    and, as a result, gives rise to unspecified behavior. That, in particular, can easily be expressed in rubbing your next-in-memory count .

    Your sprintf forms a string of at least 7 characters. To store such a string, you will need a buffer of size 8, since the string must also include a terminator null character. And you selected only the buffer size 7. Departure beyond the limits is guaranteed.

    • And you try it! I'm pretty sure that this is not a problem (on the stack on 32-bit platforms everything is aligned). - 0andriy
    • @ 0andriy: Are you kidding? The fact that this is a problem of disputes can not be. Writing 8 characters to an array of length 7 is a problem, the “problematicity” of which will not be discussed here. Everyone agrees. And it is possible to “try” as much as you like on different platforms - this is nothing more than useless experimenting with indefinite behavior. - AnT
    • Let's say that the size of the required buffer depends on the count value. With sufficiently large values, the result is guaranteed to creep beyond 7 characters (even taking into account possible alignment). With count = 100, you need 8 characters, with 1000 - already 9. Here UB is clean water, the result is unpredictable - andy.37
    • 2
      @ 0andriy again, if the behavior of the program depends on what * real executable code * generates a compiler, then this is what is called UB. - andy.37
    • four
      @ 0andriy: The early detection of UB by modern compilers and its influence on the generated code is a fact in modern compilers that is real and widespread, no matter how many different "c0ol hack0rz" squeaky about this topic. And doing divination about whether a given UB example falls into this category (that is, whether it is “in fact” or “in appearance”) is a meaningless and useless waste of time. - AnT