# Libc

Published articles for Libc.

This is one page of public article previews, not the complete archive. Follow Next page to continue. Summaries are not the original full articles.

## ESP-IDF v6.0: Default libc Switches from Newlib to PicolibC

DevFeed: [ESP-IDF v6.0: Default libc Switches from Newlib to PicolibC](<https://devfeed.tech/articles/esp-idf-v6-0-default-libc-switches-from-newlib-to-picolibc-13762.md>)

Original publisher: [Read original article](<https://developer.espressif.com/blog/2026/04/esp-idf-6-default-libc-picolibc/>)

Author: John Lee

Published: 2026-04-02T00:00:00Z

Content type: article

Language: en

Sources: [Blog on Developer Portal](<https://devfeed.tech/sources/blog-on-developer-portal.md>)

Topics: [ESP-IDF](<https://devfeed.tech/topics/esp-idf.md>), [C](<https://devfeed.tech/topics/c.md>), [Embedded Systems](<https://devfeed.tech/topics/embedded-systems.md>), [migration](<https://devfeed.tech/topics/migration.md>), [Streams](<https://devfeed.tech/topics/streams.md>), [Library](<https://devfeed.tech/topics/library.md>), [POSIX](<https://devfeed.tech/topics/posix.md>)

Tags: [apis](<https://devfeed.tech/tags/apis.md>), [architectures](<https://devfeed.tech/tags/architectures.md>), [blog](<https://devfeed.tech/tags/blog.md>), [c](<https://devfeed.tech/tags/c.md>), [compatibility](<https://devfeed.tech/tags/compatibility.md>), [embedded](<https://devfeed.tech/tags/embedded.md>), [embedded-systems](<https://devfeed.tech/tags/embedded-systems.md>), [esp-idf](<https://devfeed.tech/tags/esp-idf.md>), [firmware](<https://devfeed.tech/tags/firmware.md>), [libc](<https://devfeed.tech/tags/libc.md>), [libraries](<https://devfeed.tech/tags/libraries.md>), [memory](<https://devfeed.tech/tags/memory.md>), [migration](<https://devfeed.tech/tags/migration.md>), [newlib](<https://devfeed.tech/tags/newlib.md>), [performance](<https://devfeed.tech/tags/performance.md>), [picolibc](<https://devfeed.tech/tags/picolibc.md>), [posix](<https://devfeed.tech/tags/posix.md>), [streams](<https://devfeed.tech/tags/streams.md>), [systems](<https://devfeed.tech/tags/systems.md>), [toolchains](<https://devfeed.tech/tags/toolchains.md>)

### AI overview

ESP-IDF v6.0 changes its default C library from Newlib to PicolibC. The article compares the libraries' memory usage, standard I/O behavior, compatibility, and migration considerations, including measurements on ESP32-C3.

### Source excerpt

ESP-IDF v6.0 switches the default C library from Newlib to PicolibC. This article compares both libraries in terms of memory usage, stdio behavior, compatibility, and migration tradeoffs, and explains when keeping Newlib still makes sense.

## Why pipes sometimes get "stuck": buffering

DevFeed: [Why pipes sometimes get "stuck": buffering](<https://devfeed.tech/articles/why-pipes-sometimes-get-stuck-buffering-21115.md>)

Original publisher: [Read original article](<https://jvns.ca/blog/2024/11/29/why-pipes-get-stuck-buffering/>)

Author: Julia Evans

Published: 2024-11-29T08:23:31Z

Content type: article

Language: en

Sources: [Julia Evans](<https://devfeed.tech/sources/julia-evans.md>)

Topics: [Terminal](<https://devfeed.tech/topics/terminal.md>), [Command-line interface](<https://devfeed.tech/topics/cli.md>), [Streams](<https://devfeed.tech/topics/streams.md>)

Tags: [deep-dive](<https://devfeed.tech/tags/deep-dive.md>), [glibc](<https://devfeed.tech/tags/glibc.md>), [implementation](<https://devfeed.tech/tags/implementation.md>), [libc](<https://devfeed.tech/tags/libc.md>), [performance](<https://devfeed.tech/tags/performance.md>), [terminal](<https://devfeed.tech/tags/terminal.md>)

### AI overview

This article explains why output from commands in Unix pipelines can appear to get stuck. Programs such as grep often use block buffering when writing to a pipe, so matches may remain in memory until the buffer fills or the program exits. When output goes directly to a terminal, line buffering usually makes each line appear immediately. The behavior depends on the program's implementation and, in the case discussed, libc and glibc.

### Source excerpt

Here's a niche terminal problem that has bothered me for years but that I never really understood until a few weeks ago. Let's say you're running this command to watch for some specific output in a log file: tail -f /some/log/file | grep thing1 | grep thing2 If log lines are being added to the file relatively slowly, the result I'd see is... nothing! It doesn't matter if there were matches in the log file or not, there just wouldn't be any output. I internalized this as "uh, I guess pipes just get stuck sometimes and don't show me the output, that's weird", and I'd handle it by just running grep thing1 /some/log/file | grep thing2 instead, which would work. So as I've been doing a terminal deep dive over the last few months I was really excited to finally learn exactly why this happens. why this happens: buffering The reason why "pipes get stuck" sometimes is that it's VERY common for programs to buffer their output before writing it to a pipe or file. So the pipe is working fine, the problem is that the program never even wrote the data to the pipe! This is for performance reasons: writing all output immediately as soon as you can uses more system calls, so it's more efficient to save up data until you have 8KB or so of data to write (or until the program exits) and THEN write it to the pipe. In this example: tail -f /some/log/file | grep thing1 | grep thing2 the problem is that grep thing1 is saving up all of its matches until it has 8KB of data to write, which might literally never happen. programs don't buffer when writing to a terminal Part of why I found this so disorienting is that tail -f file | grep thing will work totally fine, but then when you add the second grep, it stops working!! The reason for this is that the way grep handles buffering depends on whether it's writing to a terminal or not. Here's how grep (and many other programs) decides to buffer its output: Check if stdout is a terminal or not using the isatty function If it's a terminal, use line b

## When printf debugging is a luxury

DevFeed: [When printf debugging is a luxury](<https://devfeed.tech/articles/when-printf-debugging-is-a-luxury-21558.md>)

Original publisher: [Read original article](<http://lackingrhoticity.blogspot.com/2010/12/when-printf-debugging-is-luxury.html>)

Author: Mark Seaborn (noreply@blogger.com)

Published: 2010-12-18T19:06:00Z

Content type: tutorial

Language: en

Sources: [Mark Seaborn](<https://devfeed.tech/sources/mark-seaborn.md>)

Topics: [debugging](<https://devfeed.tech/topics/debugging.md>), [Code](<https://devfeed.tech/topics/code.md>), [Linux](<https://devfeed.tech/topics/linux.md>), [Chromium](<https://devfeed.tech/topics/chromium.md>)

Tags: [chromium](<https://devfeed.tech/tags/chromium.md>), [code](<https://devfeed.tech/tags/code.md>), [debugging](<https://devfeed.tech/tags/debugging.md>), [glibc](<https://devfeed.tech/tags/glibc.md>), [libc](<https://devfeed.tech/tags/libc.md>), [linux](<https://devfeed.tech/tags/linux.md>), [native-client](<https://devfeed.tech/tags/native-client.md>), [sandbox](<https://devfeed.tech/tags/sandbox.md>)

### AI overview

This article explains why printf() and assert() may be unavailable in certain low-level programming contexts, including signal handlers, limited-stack environments, and code that cannot use libc. It presents a simple assertion implementation that constructs failure messages at compile time and discusses bypassing libc to invoke Linux system calls when TLS register state makes libc wrappers unusable.

### Source excerpt

Inserting printf() calls is often considered to be a primitive fallback when other debugging tools are not available, such as stack backtraces with source line numbers. But there are some situations in low-level programming where most libc calls don't work and so even printf() and assert() are unavailable luxuries. This can happen: when libc is not properly initialised yet; when we writing code that is called by libc and cannot re-enter libc code; when we are in a signal handler; when only limited stack space is available; when we cannot allocate memory for some reason; or when we are not even linked to libc. Here's a fragment of code that has come in handy in these situations. It provides a simple assert() implementation: #include <string.h> #include <unistd.h> static void debug(const char *msg) { write(2, msg, strlen(msg)); } static void die(const char *msg) { debug(msg); _exit(1); } #define TO_STRING_1(x) #x #define TO_STRING(x) TO_STRING_1(x) #define assert(expr) { \ if (!(expr)) die("assertion failed at " __FILE__ ":" TO_STRING(__LINE__) \ ": " #expr "\n"); } By using preprocessor trickery to construct the assertion failure string at compile time, it avoids having to format the string at runtime. So it does not need to allocate memory, and it doesn't need to do multiple write() calls (which can become interleaved with other output in the multi-threaded case). Sometimes even libc's write() is a luxury. In some builds of GNU libc on Linux, glibc's syscall wrappers use the TLS register (%gs on i386) to fetch the address of a routine for making syscalls. However, if %gs is not set up properly for some reason, this will fail. For example, for Native Client's i386 sandbox, %gs is set to a different value whenever sandboxed code is running, and %gs stays in this state if sandboxed code faults and triggers a signal handler. In Chromium's seccomp-sandbox, %gs is set to zero in the trusted thread. In those situations we have to bypass libc and do the system calls ourselv