Почему этот код зависает, когда я пытаюсь использовать функцию записи (man 2 write)?

Я пытаюсь написать тест, в котором некоторые данные должны быть прочитаны из файлового дескриптора, поэтому я использую функции dup и pipe для проверки этого.

 int main()
{
    char    *line;
    int     out;
    int     p[2];
    char    *str;
    int     len = 50;

    str = (char *)malloc(235436);
    for (int i = 0; i < 235436; ++i)
    {
        str[i]='h';
    }
    out = dup(1);
    pipe(p);
    dup2(p[1], 1);

    write(1, str, strlen(str)); //freezes there. malloc alocates memory, i've checked this with debuger
    close(p[1]);
    dup2(out, 1);
    get_next_line(p[0], &line);


}

И по какой-то причине этот код работает отлично, хотя он делает все то же самое.

str = (char *)malloc(1000 * 1000);
    *str = '\0';
    while (len--)
        strcat(str, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur in leo dignissim, gravida leo id, imperdiet urna. Aliquam magna nunc, maximus quis eleifend et, scelerisque non dolor. Suspendisse augue augue, tempus");
    out = dup(1);
    pipe(p);
    dup2(p[1], 1);

    if (str)
        write(1, str, strlen(str));
    close(p[1]);
    dup2(out, 1);
    get_next_line(p[0], &line);

4 ответа

Решение

Я использую трубу на машине Linux. В соответствии с этим ответом я пытаюсь прочитать больше байтов, чем может содержать pipe. Итак, в этой ситуации мне нужно создать файл с ним работать.

FILE *fptr;
fptr = fopen("buffer", "rb+");
if(fptr == NULL) //if file does not exist, create it
{
    fptr = fopen("buffer", "wb");
}

(Если вы исправите strlen проблема - то есть write(1, str, 235436))

Вы пишете в трубу. Эта труба не читается. Следовательно write будет блокировать.

Получить что-то, чтобы прочитать из трубы.

Типичный strlen реализация:

size_t strlen(char *s)
{
    size_t len = 0;
    while(*s++) len++;
    return len;
}

Другими словами, он определяет длину строки, увеличивая указатель на начало строки, пока не будет достигнут нулевой терминатор. Так как ваш буфер это просто блок персонажа 'h' без нулевого терминатора strlen на это имеет неопределенное поведение.

Ваш второй пример кода, где вы явно добавляете нулевой терминатор после вызова malloc а затем использовать strcat Повторная запись в строку не имеет этой проблемы, поскольку строковые литералы автоматически заканчиваются нулем.

Кроме того, не приводите результат malloc, если только вам не нужен код, совместимый с C++.

Проблема в вызове функции strlen!

strlen(str)

Потому что вы не установили терминатор в конце строки.

Добавление следующего кода после цикла инициализации решит проблему:

str[235435]='\0';
Другие вопросы по тегам