LINUX.ORG.RU

программа при выходе пытается написать 00a0 на stdout


0

1

в общем вопрос:

может система так и должна работать, наверно она просто добаляет символ новой строки при выходе.

write(2, "total recieve is 101702590\n", 27total recieve is 101702590
) = 27
close(1)                                = 0
close(4)                                = 0
close(3)                                = 0
brk(0x9161000)                          = 0x9161000
write(1, "\n", 1)                       = -1 EBADF (Bad file descriptor)
exit_group(0)                     

это вывод strace

а вот исходник

    fprintf(stderr, "total recieve is %d\n", t_recv);
    close(f_desc);
    free(buffer);
    exit(0);

никаких вызовов write перед выходом нет.

в общем, если это стандартное поведение системы, то соответственно вопрос.

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

как этого избежать, как-то закрытие stdout перед выходом из программы мне не нравится, система ругается и по видимому это не тру вей.

★★

Ответ на: комментарий от visual

дескриптор файла, это как раз и есть stdout

я закрываю его перед выходом и проблема решается, но по моему это как-то не правильно

IvanR ★★ ()
Ответ на: комментарий от visual

если бы не закрывал, то система вписала бы перевод строки в файл, в который я перенаправляю stdout.

в моей программе вообще нет этого вызова write, у меня сразу после закрытия дескрипторов идет exit, но поскольку я перенаправлял вывод при вызове программы, то туда дописывается перевод строки, который там не нужен.

вообще мне не ясно, почему система делает этот вызов, это не моя программа.

IvanR ★★ ()
Ответ на: комментарий от IvanR
#include <stdio.h>

int main(int argc, char ** argv)
{


    fprintf(stdout,"Hello");
    exit(0);
    return 0;
}
[guilder@localhost lt]$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 22 vars */]) = 0
brk(0)                                  = 0x8383000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb770d000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=72791, ...}) = 0
mmap2(NULL, 72791, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb76fb000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220\27?E4\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=2011688, ...}) = 0
mmap2(0x453d8000, 1776316, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x453d8000
mprotect(0x45583000, 4096, PROT_NONE)   = 0
mmap2(0x45584000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ab) = 0x45584000
mmap2(0x45587000, 10940, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x45587000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76fa000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb76fa6c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0x45584000, 8192, PROT_READ)   = 0
mprotect(0x453d4000, 4096, PROT_READ)   = 0
munmap(0xb76fb000, 72791)               = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb770c000
write(1, "Hello", 5Hello)                    = 5
exit_group(0)                           = ?
+++ exited with 0 +++

Я что-то никаких вызовов не наблюдаю, но

#include <stdio.h>

int main(int argc, char ** argv)
{

    close(stdout);
    fprintf(stdout,"Hello");
    exit(0);
    return 0;
}

даёт

[guilder@localhost lt]$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 22 vars */]) = 0
brk(0)                                  = 0x9357000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb779b000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=72791, ...}) = 0
mmap2(NULL, 72791, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7789000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220\27?E4\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=2011688, ...}) = 0
mmap2(0x453d8000, 1776316, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x453d8000
mprotect(0x45583000, 4096, PROT_NONE)   = 0
mmap2(0x45584000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ab) = 0x45584000
mmap2(0x45587000, 10940, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x45587000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7788000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb77886c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0x45584000, 8192, PROT_READ)   = 0
mprotect(0x453d4000, 4096, PROT_READ)   = 0
munmap(0xb7789000, 72791)               = 0
close(1163422208)                       = -1 EBADF (Bad file descriptor)
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb779a000
write(1, "Hello", 5Hello)                    = 5
exit_group(0)                           = ?
+++ exited with 0 +++

visual ★★★ ()
Ответ на: комментарий от visual

но

#include <stdio.h>

int main(int argc, char ** argv)
{

    fclose(stdout);
    fprintf(stdout,"Hello");
    exit(0);
    return 0;
}

даёт

execve("./a.out", ["./a.out"], [/* 22 vars */]) = 0
brk(0)                                  = 0x9767000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7786000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=72791, ...}) = 0
mmap2(NULL, 72791, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7774000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220\27?E4\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=2011688, ...}) = 0
mmap2(0x453d8000, 1776316, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x453d8000
mprotect(0x45583000, 4096, PROT_NONE)   = 0
mmap2(0x45584000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ab) = 0x45584000
mmap2(0x45587000, 10940, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x45587000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7773000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb77736c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0x45584000, 8192, PROT_READ)   = 0
mprotect(0x453d4000, 4096, PROT_READ)   = 0
munmap(0xb7774000, 72791)               = 0
close(1)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

И сразу наводка, нет ли у программы обработки сигналов

visual ★★★ ()

stdio буферизует stdout. При выходе из программы вызывается fflush(stdout), который рассчитывает, что дескриптор 1 еще открыт.

Ищи лишний '\n' в своем коде, как то же он в буфер попадает.

anonymous ()

Ну ты баклан. fprintf(3) - функция libc, которая формирует строку и выводи её с помощью (ядерного) сискола write(2).

strace показывает сисколы, а не библиотечные вызовы.

anonymous ()
Ответ на: комментарий от visual

А результат close() кто проверять будет?

anonymous ()
Ответ на: комментарий от anonymous

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

anonymous ()
Ответ на: комментарий от anonymous

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

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

./prog > filename

то при выходе система пытаеся запихнуть в stdout (в данном случае «filename») '\n' в принципе пофиг, так как перед выходом я закрываю дескриптор.

но мне просто интеерсно, какое объяснение можно придумать такому поведению

IvanR ★★ ()
Ответ на: комментарий от IvanR

В приведённом вами исходнике вобще нет ни одного fprintf(stdout,...) или куда ещё, кроме потока stderr. Так что, либо давайте компилируемый исходник, дающий такое поведение, либо ищите, где вы пишете лишний '\n' в поток stdout, после того, как делаете fflush(), так что в буфере stdout остаётся только этот '\n'.

Или можете попробовать отключить буферизацию вывода на stdout через setvbuf(_IONBF) и буферизацию других потоков вывода (создаваемых через fopen()/fdopen()) и посмотреть, появляется ли этот '\n' в файле и в конце ли файла он появляется.

так вот если программе непосредственно задать имя файла, то она запишет вывод в этот файл

Программа просто пишет в этот файл через отдельный файловый дескриптор или заменяет им STDOUT через dup2()?

mky ★★★★★ ()
Последнее исправление: mky (всего исправлений: 1)
Ответ на: комментарий от mky

нет, не заменяет, открывает функцией open и дальше пишет функцией write(f_desc,...) если имя фала не задается, то f_desc = 1 и дальше опять аналогичный код и функция write

весь «служебный вывод делается fprintf(stderr,...) нет вообще ниодного вызова fprintf(stdout,...)

в начале программы идет разбор параметров и если параметр --filename не встречается, то в качестве filename устанавливается '-', дальше, если filename == '-' тогда f_desc = 1 или f_desc = open(filename)

    c_write_m = 0;
    t_recv = 0;
    while (c_recv = recv(sock_remote, buffer, connect_params.buf_len, 0)) {
        if (c_recv == -1) {
            perror("recv");
            exit(1);
        }
        c_write = 0;
        while (c_write < c_recv) {
            c_write_m = write(f_desc, buffer + c_write, c_recv - c_write);
            if (c_write_m == -1) {
                perror("write");
                exit(1);
            }
            c_write += c_write_m;
        }
        t_recv += c_recv;
    }
    fprintf(stderr, "total recieve is %d\n", t_recv);
    close(f_desc);
    if (close(sock_remote) == -1) {
        perror("close");
    }
    close(sock);
    free(buffer);
    exit(0);    
IvanR ★★ ()
Ответ на: комментарий от IvanR

Вобще система ничего не должна добавлять. После exit() идёт только сброс буферов потокового вывода (STDOUT). Этого же можно добится с помощью fflush(). Попробуйте сделать fflush(stdout) перед close(f_desc) и, если лишний '\n' попадёт в файл, значит exit() не виноват.

Если вашу программу запустить с указанием имени файла и с перенаправлением stdout в файл, то этот файл будет содержать '\n'?

Сделать setvbuf(stdout, NULL, _IONBF, 0) и посмотреть появляется ли в файле лишний '\n' при перенаправлении вывода в файл через '>' не пробовали?

mky ★★★★★ ()
Ответ на: комментарий от mky

да, программа при выходе добавляет один '\n' в файл stdout, но он не попадает в файл, который задается программе как параметр, так как дескриптор файла уже не 1

в общем вот вывод strace

recv(5, "#include <ctype.h>\n#include <str"..., 1048576, 0) = 13698
write(3, "#include <ctype.h>\n#include <str"..., 13698) = 13698
recv(5, "", 1048576, 0)                 = 0
write(2, "total recieve is 13698\n", 23total recieve is 13698
) = 23
close(3)                                = 0
close(5)                                = 0
close(4)                                = 0
munmap(0xb7531000, 1052672)             = 0
write(1, "\n", 1)                       = 1
exit_group(0)                           = ?
IvanR ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.