Member 12919791 Ответов: 1

PSET4 восстановление ошибки сегментации


В этом коде я хочу записать 50 jpg из файла.

(фактические инструкции: )[^]

This is the terminal output:
~/workspace/pset4/jpg/ $ make recover clang -fsanitize=integer -fsanitize=undefined -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wshadow recover.c -lcrypt -lcs50 -lm -o recover ~/workspace/pset4/jpg/ $ ./recover

---Segmentation fault---

With valgrind, I see that there are no leaks, but a line says that no memory allocations were made:

Invalid read of size 4 ==17227== at 0x5E268D4: fclose@@GLIBC_2.2.5 (iofclose.c:54) ==17227== by 0x42DB5F: main (recover.c:85)

==17227== Address 0x0 is not stack'd, malloc'd or (recently) free'd

==17227== 
==17227== 
==17227== Process terminating with default action of signal 11 (SIGSEGV) 
==17227== Access not within mapped region at address 0x0 
==17227== at 0x5E268D4: fclose@@GLIBC_2.2.5 (iofclose.c:54) 
==17227== by 0x42DB5F: main (recover.c:85) ==17227== If you believe this happened as a result of a stack 
==17227== overflow in your program's main thread (unlikely but 
==17227== possible), you can try to increase the size of the 
==17227== main thread stack using the --main-stacksize= flag. 
==17227== The main thread stack size used in this run was 8388608. 
==17227== 
==17227== HEAP SUMMARY: 
==17227== in use at exit: 0 bytes in 0 blocks 
==17227== total heap usage: 1 allocs, 1 frees, 568 bytes allocated =
=17227== 
==17227== All heap blocks were freed -- no leaks are possible 
==17227== 
==17227== For counts of detected and suppressed errors, rerun with: -v 
==17227== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
 Segmentation fault

Thanks a lot,


Что я уже пробовал:

/**
 * recover.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * Recovers JPEGs from a forensic image.
 */
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <stdint.h>



int main()
{
    typedef uint8_t BYTEINBITS;

    int pictcount = 0;
    
    
    FILE* input = fopen("card.raw", "r");
 
     if ( input == NULL )
    {
        printf(" Could not open card.raw \n");
        return 2;
    }
    
    FILE* output = NULL;
    
    bool  atend = false;
    
    while ( atend == false)
    {
        BYTEINBITS buffer[512];

         
        fread( &buffer, 512 * sizeof(char), 1, input); 
 
         
        bool jpg = true;
        
        if ( !( ( buffer[0] == 255 ) && ( buffer[1] == 216 ) && ( buffer[2] == 255) && ( buffer[3] > 224 ) ) )         
        {
            jpg = false;
        }
 
         
        if (jpg == true)
        {
             
             if (pictcount >= 1)
             {
              
                  fclose(output);   
             }         
                 
            pictcount++;
            char title[8];
            sprintf(title,"%03d.jpg", pictcount);
            
            output  = fopen("title", "w");
        
        }
        
        if (pictcount > 0)
        {
         
            fwrite( &buffer, 512 * sizeof(char), 1, output );

        }
        
        if ( fread( &buffer, 512*sizeof(char), 1, input) != 1)
        {
            atend = true;   
        }
    }
     
    fclose(input);
    fclose(output);


    
    
}

1 Ответов

Рейтинг:
5

Jochen Arndt

Ошибка здесь:

BYTEINBITS buffer[512];
fread( &buffer, 512 * sizeof(char), 1, input); 

buffer является массивом и поэтому уже является указателем, но вы передаете адрес этого указателя fread (вы передаете указатель на указатель вместо указателя).

Рабочая версия должна выглядеть так:
uint8_t buffer[512];
fread(buffer, sizeof(buffer), 1, input); 

Обратите внимание, что я также удалил бесполезное typedef для uint8_t (это делает код менее читаемым), фиксированный размер буфера 512 и sizeof(char) (что не всегда может совпадать с sizeof(uint8_t)). Просто использовать sizeof(buffer) который расширяется до размера массива в байтах.


Member 12919791

Я понимаю ошибку выше, но та же ошибка возникает даже после того, как я изменил эту строку.

Jochen Arndt

Я показал только первую строку, содержащую ошибку, но она должна быть исправлена для всех вызовов fread и fwrite.

Member 12919791

Да, изменения внесены и в другие Фрейды