2009-02-01 4 views
8

printf를 사용하여 stdout으로 메시지를 보내고 bash에서 실행중인 파일로 출력을 리디렉션하는 데 문제가 있습니다.bash에서 C 프로그램 출력을 리디렉션 할 때 문제가 발생했습니다.

이 나는 ​​시도했다 : 각각의 경우에

./program argument >> program.out 
./program argument > program.out 
./program >> program.out argument 
./program > program.out argument 

는 파일 program.out이 만들어집니다하지만 비어 있습니다. 실행이 종료 한 후, 파일 크기는 프로그램 실행시 저는 재를 생략하면 0

이다 :

./program argument 

그런 다음의 printf를 사용하여 표준 출력에 전송 된 모든 메시지는 상기 단말에 나타낸다.

나는이 방법으로 출력을 리디렉션하는 데 문제가없는 다른 C 프로그램을 가지고 있습니다. 프로그램 자체와 관련이 있습니까? 인수가 지나가고? 어디에서 문제를 찾아야합니까?

C 프로그램에 대한 몇 가지 세부 사항 : 그것은 그것은 POSIX 그것은위한 특별한 핸들러 함수를 할당

  • 스레드 사용
  • BSD 인터넷 도메인 소켓을 사용
  • 을 stdin에서 아무것도 읽지 않습니다

    • sigaction을 사용하는 SIGINT 신호
    • 많은 수의 개행 문자를 stdout으로 보냅니다. (플러시해야한다고 생각하는 사람들을 위해)

    일부 코드 : 파일로 인쇄 할 때 반드시하지만, 터미널에 인쇄 할 때

    int main(int argc, char** argv) 
    { 
        printf("Execution started\n"); 
        do 
        {   
         /* lots of printf here */ 
        } while (1); 
        /* Code never reached */ 
        pthread_exit(EXIT_SUCCESS); 
    } 
    
  • +0

    출력 재 지정없이 동일한 프로그램이 화면에 대한 출력을 생성합니까? – womble

    +0

    나는 그것을 명확하게하기 위해 질문을 편집했다. 감사합니다. – mmutilva

    답변

    14

    세척 후 줄 바꿈에만 작동합니다. 빠른 Google 검색을 통해이 페이지에 자세한 정보가 표시되었습니다. http://www.pixelbeat.org/programming/stdio_buffering/

    "기본 버퍼링 모드"섹션을 참조하십시오.

    결국 fflush (stdout)에 대한 호출을 추가해야 할 수도 있습니다.

    setvbuf을 사용하여 버퍼 크기와 동작을 설정할 수도 있습니다.

    +1

    프로그램이 종료되면 어떨까요? stdout이 자동으로 플러시되지 않아야합니까? – mmutilva

    +0

    터미널과 파일을 보내는 중이 다른 stdout 버퍼 동작에 대한 정보가있는 링크가 있습니까? – mmutilva

    +0

    내 응답에 대한 링크를 편집하여 누구나 쉽게 볼 수 있습니다. 명시 적으로 모든 것을 플러시하는 대신 setvbuf (또한 내 대답에 링크 됨)를 사용하여 버퍼링 동작을 변경할 수 있습니다. – gclj5

    3

    리디렉션 된 파일의 내용을 확인할 때까지 프로그램이 종료 되었습니까? 아직 실행중인 경우 출력이 계속 체인의 어딘가에 버퍼링 될 수 있으므로 파일에 표시되지 않습니다.

    지금까지 제공된 다른 답변과는 별도로 문제 코드의 대표적인 예를 보여줄 때라고 생각합니다. 너무 많은 비밀 가능성이 있습니다. 당신이 인쇄 발생의 상대적으로 적은 양을 가지고있는 경우에

    샘플 코드의 모양에서 편집

    는, 당신은 출력 버퍼에 걸리지 있습니다. 각 쓰기 후에 플러시하여 디스크로 이동했는지 확인하십시오. 일반적으로 최대 한 페이지 크기의 가치가 비공개 데이터 주위에있을 수 있습니다.

    플러시가없는 경우 프로그램이 종료 될 때만 디스크에 모든 것이 있는지 확인할 수 있습니다. 종료 된 쓰레드조차도 그렇게하지 않을 것입니다. 왜냐하면 그것과 같은 출력 버퍼는 쓰레드가 아니기 때문에 프로세스마다 있습니다.

    +0

    작은 프로그램에서 그것을 재현 할 수 없었고 원본 프로그램을 게시하기가 커졌습니다. 어쨌든 일부 코드를 보여 주려고 노력할 것입니다. – mmutilva

    6

    버퍼 플러시는 일반적으로 exit() 함수에 의해 처리됩니다.이 함수는 일반적으로 main()에서 return에 의해 암시 적으로 호출됩니다. SIGINT를 올려 프로그램을 끝내고 있으며, 디폴트 SIGINT 핸들러가 버퍼를 비우지 않는 것 같습니다.

    Applying Design Patterns to Simplify Signal Handling이 기사를 살펴보십시오. 이 기사는 대부분 C++이지만 2 단원에는 SIGINT를 사용하여 프로그램을 정상적으로 종료하는 방법을 보여주는 유용한 C 예가있다.

    터미널의 동작이 파일과 다른 이유는 스티븐스의 Advanced Programing in the UNIX Environment 섹션 5.4 버퍼링을 살펴보십시오. 그는 이렇게 말합니다 :

    대부분의 구현은 기본적으로 다음 유형의 버퍼링을 사용합니다. 표준 오류는 항상 버퍼링되지 않습니다. 다른 모든 스트림은 터미널 장치를 나타내는 경우 줄 바꿈됩니다. 그렇지 않으면 완전히 버퍼링됩니다. 이 책에서 설명하는 네 개의 플랫폼은 표준 I/O 버퍼링에 대한 다음 규칙을 따릅니다. 표준 오류는 버퍼링되지 않고 터미널 장치에 열린 스트림은 줄 버퍼이며 다른 모든 스트림은 완전히 버퍼링됩니다.
    0

    제안 :뿐만 아니라 파일에

    1. 리디렉션 표준 에러.
    2. 출력 파일을 tail -f로 시도하십시오.
    3. 로깅을 사용하여 파일을 열고 로그를 남깁니다.
    4. std * FILE 핸들 또는 1-3 파일 설명 자의 수동 닫기/복제/파이핑을 검색합니다.
    5. 복잡도 줄이기; printfs가 작동 할 때까지 기능의 큰 덩어리를 잘라냅니다. 그런 다음 다시 깨질 때까지 읽으십시오. 범인 코드를 확인할 때까지 계속하십시오.
    0

    그냥 기록을 위해, 펄에서 다음을 사용 :

    use IO::Handle; 
    
    flush STDOUT; 
    autoflush STDOUT; 
    
    관련 문제