Fread один int из файла bin дает мне ошибку сегментации в C

Я хочу вашей помощи в чем-то, что должно быть легко, и я не знаю, почему это не работает. Я хочу прочитать первые данные из бина, который я знаю, что это int. Я использую следующую часть кода, но получаю ошибку сегментации:

int main(int argc, char **argv)
    {
        int *data;
        /*opening file*/
        FILE *ptr_myfile;
        ptr_myfile=fopen(myfile.bin","rb");
        if (!ptr_myfile)
        {
            printf("Unable to open file!\n");
            return 1;
        }
        /*input file opened*/
        printf("I will read the first 32-bit number\n");
        /*will read the first 32 bit number*/
        fread(&data,sizeof(int),1, ptr_myfile);
        printf("Data read is: %d\n",*data);     

        fclose(ptr_myfile);
        return 0;
    }

Я также попытался назвать это так:

fread(data,sizeof(int),1, ptr_myfile);

Это должно быть что-то с указателем, но я не вижу, что.

4 ответа

Решение

Изменить:

  • int *data; в int data;
  • printf("Data read is: %d\n",*data); в printf("Data read is: %d\n",data);

Вы читаете int в указатель, затем пытается разыменовать указатель (который имеет значение, которое не имеет смысла как указатель).

У вас нет памяти, выделенной для data и в первом примере кода вы не используете указатель правильно. Это альтернатива, которая может работать:

int data;

и тогда вы будете использовать это так:

fread(&data,sizeof(int),1, ptr_myfile);

В исходном коде вы пишете int в указатель:

fread(&data,sizeof(int),1, ptr_myfile) ;

а потом это *data будет разыменовывать неверный указатель. В альтернативном случае:

fread(data,sizeof(int),1, ptr_myfile);

Вы будете использовать указатель, которому не выделена память.

Вы передаете адрес нераспределенного указателя. Удалить * от data:

int data;
...
fread(&data, sizeof(int), 1, ptr_myfile);

Вы переосмысливаете вопрос об указателях. Функция fread() Нужно знать адрес, по которому хранятся данные, которые он читает, поэтому ему передается указатель. Это не значит, что буфер используется fread должен быть указатель, просто это fread нужен указатель на этот буфер.

Итак, ваша первая ошибка пишет int *data; где вы на самом деле просто имеете в виду int data;, Вы говорите, что элемент данных для чтения является intтак что вы просто объявите int держать его.

Ты правильно звонил fread читать данные, передавая указатель на фактически выделенную и действительную память (т.е. &data), избегая другой ловушки новичка в передаче неинициализированного указателя на целое число, которое вы объявили ранее.

Ваша фактическая ошибка вызвана записью *data в призыве к printf, * Оператор берет указатель и разыменовывает его. Другими словами, предполагается, что указатель указывает на что-то, и извлекает это значение. Однако, когда указатель, на который делается разыменование, не указывает ни на что допустимое, возникает проблема.

И вот где тебе повезло. Значение, которое вы прочитали из файла, было обработано * оператор как адрес в памяти, но оказался адресом, который не был частью памяти, доступной для вашего процесса, что заставило систему обратить внимание и остановить процесс из-за ошибки сегментации. В результате вы сразу узнали, что в вашем коде произошла ошибка.

Если вам не повезло, целое число, которое вы читаете из файла, если рассматривать его как адрес памяти, могло бы быть адресом чего-то, что уже присутствует в вашем процессе. Вы не вызвали бы ошибку сегментации, и вы были бы озадачены, почему printf выдал странный ответ.

Теперь представьте, что вы читаете значение из ненадежного источника и рассматриваете его как произвольный адрес. Злоумышленник может использовать эту ошибку, чтобы узнать что-нибудь о вашей программе. Хуже того, если вы записали в память, на которую ссылается этот указатель, злоумышленник может изменить поведение вашей программы.

В заключение отметим, что чтение и письмо int (или любой другой тип данных) является безопасным и приемлемым, если этот файл никогда не будет передан в другую систему. Не все системы согласуются даже с простейшими определениями, такими как число байтов, занимаемых целым числом (которое вы правильно обработали, используя sizeof(int), но не таким способом, который позволял бы обмениваться файлом с системой с другим целочисленным размером), или даже порядком тех байтов в памяти. Правильное решение этих вопросов - большая тема.

Другие вопросы по тегам