Почему эта программа дает ошибку сегментации?

Это программа, которую я написал для проверки байтов между файлом и диском.

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

#define BYTES_TO_READ 64

int main(int argc, char **argv)
{
  int device = open("/dev/sdz", O_RDWR);
  if(device < 0)
  {
      printf("Device opening error\n");
      return 1;
  }
  int file = open("test.txt", O_RDONLY);
  if(file < 0)
  {
      printf("File opening error\n");
      return 2;
  }
  int byte, device_loc, file_loc;
  char *buff_device, *buff_file;
  for(byte = 0; byte<BYTES_TO_READ; byte++)
  {
      device_loc = lseek(device, byte, SEEK_SET); /* SEG FAULT */
      file_loc = lseek(file, byte, SEEK_SET);
      printf("File location\t%d",file_loc);
      printf("Device location\t%d",device_loc);
      read(device, buff_device, 1);
      read(file, buff_file, 1);
      if( (*buff_device) == (*buff_file) )
      {
          printf("Byte %d same", byte);
      }
      else
      {
          printf("Bytes %d differ: device\t%d\tfile\t%d\n",byte, *buff_device, *buff_file);
      }
  }
  return 0;
}

Пожалуйста, не спрашивайте, почему я сравниваю sdz и файл. Это именно то, что я хотел сделать: записать файл прямо на диск и прочитать его обратно.

sdz — это устройство обратной связи со ссылкой на /dev/loop0. Пока неважно, отличаются ли файл и диск, но я хочу, чтобы моя программа работала. С помощью некоторой отладки я нашел, где происходит ошибка сегментации, но я не мог понять, почему.

Короче говоря: почему это дает мне ошибку сегментации?

заранее спасибо


person vfsoraki    schedule 27.02.2014    source источник
comment
buff_device выглядит неинициализированным.   -  person chux - Reinstate Monica    schedule 27.02.2014
comment
Я упомянул, что sdz — это петлевое устройство. Была бы какая-то разница, если бы это был настоящий диск?   -  person vfsoraki    schedule 27.02.2014


Ответы (2)


Они пишут в случайные места в памяти:

read(device, buff_device, 1);
read(file, buff_file, 1);

поскольку buff_device и buff_file являются неинициализированными указателями. Используйте тип char и вместо этого передайте их адреса.

char buff_device;
char buff_file;

/* Check return value of read before using variables. */
if (1 == read(device, &buff_device, 1) &&
    1 == read(file, &buff_file, 1))
{
    if (buff_device == buff_file)
    /* snip */
}
else
{
    /* Report read failure. */
}
person hmjd    schedule 27.02.2014
comment
Я думал, что read будет выделять память, а затем помещать ее адрес в буферы, предоставленные для работы. Так что нет, да? - person vfsoraki; 27.02.2014
comment
@thelastblack, нет, память не выделяется. - person hmjd; 27.02.2014
comment
@thelastblack Просто мысленный эксперимент: если read() выделил память, как это повлияет на buff_device? buff_device — это указатель (на ла-ла-ланд в настоящее время), и это значение присваивается read(). Что бы read() ни сделал со своей копией этого значения, это не повлияет на исходное buff_device. - person chux - Reinstate Monica; 27.02.2014
comment
@чукс, верно. Если бы read() выделял память, то в качестве аргумента необходимо было бы передать указатель на указатель, чтобы вызывающая сторона могла увидеть изменение. - person hmjd; 27.02.2014
comment
@chux Когда я думаю об этом, вы, ребята, совершенно правы. Я не большой программист на C. В основном я пишу сценарии, в которых не используются указатели :D Спасибо за разъяснения. - person vfsoraki; 27.02.2014
comment
Не могли бы вы взглянуть на комментарии к вопросу и ответить мне, если сможете? - person vfsoraki; 27.02.2014
comment
@thelastblack, какой вопрос? - person hmjd; 27.02.2014
comment
Это вопрос, на который вы ответили! Этот вопрос, пожалуйста, ознакомьтесь с комментариями ниже самого вопроса. - person vfsoraki; 27.02.2014
comment
@thelastblack, боюсь, я этого не знаю. Извиняюсь. - person hmjd; 27.02.2014

Изменять :

char *buff_device, *buff_file;

to

char buff_device[1], buff_file[1];
person Jabberwocky    schedule 27.02.2014