чтение файла, который не существует - PullRequest
2 голосов
/ 19 февраля 2011

У меня есть небольшая программа, которая печатает содержимое файлов с помощью системного вызова - прочитайте.

unsigned char buffer[8];
size_t offset=0;
size_t bytes_read;

int i;

int fd = open(argv[1], O_RDONLY);

do{
    bytes_read = read(fd, buffer, sizeof(buffer));
    printf("0x%06x : ", offset);

    for(i=0; i<bytes_read; ++i)
    {
        printf("%c ", buffer[i]);
    }
    printf("\n");
    offset = offset + bytes_read;
}while(bytes_read == sizeof(buffer));

Теперь во время работы я даю имя файла, который не существует. Он печатает какие-то данные, смешанные с переменными среды и ошибкой сегментации в конце.

Как это возможно? Что такое программа печати?

Спасибо, John

Ответы [ 4 ]

7 голосов
/ 19 февраля 2011

Это печатный мусор, потому что fd всегда будет установлен в -1, что не очень хорошая вещь для передачи в read, поскольку он, в свою очередь, не будет делать ничего, кроме возврата -1.Это оставит ваш буфер нетронутым, что означает, что он содержит весь мусор, который был у вас там при запуске.

Возможно, вы могли бы поместить весь цикл do в нечто вроде:

if (fd == -1) {
    printf ("error here");
} else {
    // do loop here
}
5 голосов
/ 19 февраля 2011

read возвращает -1, потому что fd недопустим, вы сохраняете это в bytes_read, который имеет тип size_t, который не имеет знака, поэтому ваш цикл печатает (size_t) -1 символ, который является очень большим числом, намного большим, чем размер буфера. Итак, вы распечатываете большую часть вашего адресного пространства, а затем получаете ошибку, когда в конце концов достигаете конца и получаете доступ к неверному адресу.

Как уже упоминали другие (не отвечая на ваш фактический вопрос), вы должны проверять результаты открытия на наличие ошибок. например,

int fd = open(argv[1], O_RDONLY);
if( fd < 0 ){
    fprintf(stderr, "error opening %s: %s\n", argv[1], strerror(errno));
    exit(1);
}

Предупреждение: если вы делаете другой системный вызов или вызываете любую подпрограмму, которая может выполнить системный вызов (например, printf) перед вызовом strerror, вы должны сохранить errno и затем передать сохраненную копию в strerror.

Еще одна заметка о вашей программе:

while(bytes_read == sizeof(buffer))

Это не очень хороший тест, потому что read может вернуть меньше, чем вы просите. Ваш цикл должен продолжаться, пока чтение не вернется <= 0. </p>

1 голос
/ 19 февраля 2011

Вам, вероятно, следует проверить, что дескриптор файла, возвращаемый open, действителен перед его использованием. Согласно этим документам , вы должны получить неотрицательный ответ для действительного файла. Чтение из неверного дескриптора, вероятно, является источником вашей проблемы.

0 голосов
/ 19 февраля 2011

После успешного завершения функция open должна открыть файл и вернуть неотрицательное целое число, представляющее дескриптор файла.В противном случае должно быть возвращено -1 и установлено значение errno, указывающее на ошибку.Поэтому, пожалуйста, проверьте fd перед входом в цикл, чтобы выполнить чтение.

...