pico-sdk icon indicating copy to clipboard operation
pico-sdk copied to clipboard

Inconsistent ordering of output to STDOUT

Open Memotech-Bill opened this issue 2 years ago • 1 comments

I have found that mixing different methods of writing to stdout results in inconsistent ordering of the output.

The following simple program illustrates this:

// Test sequencing of STDOUT

#include <pico.h>
#include <pico/time.h>
#include <pico/stdio.h>
#include <pico/stdio_usb.h>
#include <stdio.h>

int main (int argc, const char **argv)
    {
    stdio_init_all();
    while ( ! stdio_usb_connected() ) sleep_ms(1000);
    char a = 'A';
    char b = 'B';
    fwrite (&a, 1, 1, stdout);      // Output the character 'A'
    printf ("%c", b);               // Output the character 'B'
    fflush (stdout);
    printf ("\n");
    }

Clearly the expected output is AB. However, in practice the output is BA.

The CMakeLists.txt file I am using is:

cmake_minimum_required(VERSION 3.12)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(sio_test C CXX ASM)
pico_sdk_init()
add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME}
  pico_stdlib
  pico_time
  pico_stdio
  pico_stdio_usb
  )
pico_enable_stdio_usb(${PROJECT_NAME} 1)
pico_add_extra_outputs(${PROJECT_NAME})

Memotech-Bill avatar Sep 12 '23 19:09 Memotech-Bill

A slightly refined example with the same result

// Test sequencing of STDOUT

#include <pico.h>
#include <pico/time.h>
#include <pico/stdio.h>
#include <pico/stdio_usb.h>
#include <stdio.h>

int main (int argc, const char **argv)
    {
    stdio_init_all();
    while ( ! stdio_usb_connected() ) sleep_ms(1000);
    char a = 'A';
    char b = 'B';
    fprintf (stdout, "%c", a);      // Output the character 'A'
    printf ("%c", b);               // Output the character 'B'
    fflush (stdout);
    printf ("\n");
    }

Memotech-Bill avatar Sep 13 '23 19:09 Memotech-Bill

This is because we try to reduce code size by preventing the HUGE amount of FILE handling code used by fprintf and friends from being pulled in just for a simple printf. This means that printf does not go thru the C-library, whereas fprintf does, and the latter is what is buffering.

You can fix your problem, by moving the fflush(stdout) after the fprintf, but also we will be adding

PICO_STDIO_SHORT_CIRCUIT_CLIB_FUNCS define in the next release, which you can set to 0 to for output from printf to go thru the c-library

kilograham avatar Jul 20 '24 19:07 kilograham

You can set PICO_STDIO_SHORT_CIRCUIT_CLIB_FUNCS=1 in your target_compile_options if you want to mix printf and fprintf(stdout). The reason we don't do that by default is that otherwise you pull in all the C library FILE handling code

kilograham avatar Aug 09 '24 19:08 kilograham