lseek() возвращает 0, когда за ним следует new open()

У меня есть следующий фрагмент кода (это "пример" кода, так что ничего особенного):

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    char buffer[9];
    int fp = open("test.txt", O_RDONLY);

    if (fp != -1) // If file opened successfully
    {
        off_t offset = lseek(fp, 2, SEEK_SET); // Seek from start of file
        ssize_t count = read(fp, buffer, strlen(buffer));
        if (count > 0) // No errors (-1) and at least one byte (not 0) was read
        {
            printf("Read test.txt %d characters from start: %s\n", offset, buffer);
        }

        close(fp);
    }

    int fp2 = open("test.txt", O_WRONLY);
    if (fp2 != -1)
    {
        off_t offset = lseek(fp2, 2, SEEK_CUR); // Seek fraom current position (0) - same result as above in this case
        ssize_t count = write(fp2, buffer, strlen(buffer));
        if (count == strlen(buffer)) // We successfully wrote all the bytes
        {
             printf("Wrote to test.txt %d characters from current (0): %s\n", offset, buffer);
        }

        close(fp2);
    }
}

Этот код не возвращает первую распечатку (чтение) как есть, а вторая распечатка гласит: «Записал в test.txt 0 символов из текущего (0):», что указывает на то, что он нигде не искал в файле и что буфер пуст. .

Странно то, что если я закомментирую все, начиная с fp2 = open("test.txt", O_WRONLY);, первая распечатка вернет то, что я ожидал. Как только я включу второй оператор open (даже ни с чем другим), он не запишет его. Это как-то переупорядочивает открытые операторы или что-то еще?


person Christian P.    schedule 10.01.2010    source источник
comment
Это, конечно, не переупорядочивает вызовы для открытия.   -  person bmargulies    schedule 10.01.2010


Ответы (2)


Линия

ssize_t count = read(fp, buffer, strlen(buffer));

неверно, вы берете strlen неинициализированного буфера. Вероятно, вы хотите, чтобы размер буфера был таким:

ssize_t count = read(fp, buffer, sizeof buffer);

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

if (fp != -1) // If file opened successfully
{

    off_t offset = lseek(fp, 2, SEEK_SET); // Seek from start of file
    ssize_t count = read(fp, buffer, sizeof buffer - 1);
    if (count > 0) // No errors (-1) and at least one byte (not 0) was read
    { 
       buffer[count] = 0;
person nos    schedule 10.01.2010
comment
Кажется, работает. Кажется, что в некоторых экземплярах программы буфер заполнялся мусором при запуске, заставляя ее работать, а иногда и нет (в этом конкретном случае). Я и память... - person Christian P.; 10.01.2010
comment
buffer, будучи автоматической переменной, не инициализируется значением 0, поэтому содержит случайные значения. Если бы buffer был static или глобальным, он был бы инициализирован всеми байтами 0. - person Alok Singhal; 10.01.2010

Вы абсолютно уверены, что очищаете файл каждый раз, когда запускаете?

Как написано, при первом запуске вы увидите только вторую распечатку, а во второй раз вы можете увидеть первую.

person bmargulies    schedule 10.01.2010