C++ String strerror() Function

Beginner
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples
Error handling

What You’ll Learn

When a C or C++ library call fails, it often sets the global variable errno to a numeric error code. The strerror() function turns that number into a plain-English message like No such file or directory—so users and developers understand what went wrong without memorizing error constants.

01

errno Codes

System errors.

02

Readable Text

Human messages.

03

char* Return

Library string.

04

vs perror()

Return vs print.

05

File I/O

fopen failures.

06

<cerrno>

ENOENT, EINVAL.

Definition and Usage

In C++, strerror() is declared in <cstring>. You pass an integer error code—usually the value of errno immediately after a failed system call—and receive a pointer to a short descriptive C-string managed by the C library.

This function does not clear or modify errno. It only translates a number you supply. Messages are defined by the operating system and may vary slightly between platforms, but common codes like ENOENT and EACCES produce familiar text on most systems.

💡
Beginner Tip

Save errno to a local variable right after a failure: int err = errno; then call strerror(err). Other functions (including strerror itself on some platforms) may change errno before you read it again.

📝 Syntax

Function signature and required headers:

C++
#include <cstring>
#include <cerrno>

char* strerror(int errnum);

// Typical usage after a failed call:
// int err = errno;
// const char* msg = strerror(err);

Parameters

  • errnum — an error number, commonly errno or a constant like ENOENT.

Return Value

Returns a pointer to a null-terminated message string. The storage is owned by the library—copy it if you need to keep the text beyond the next call to strerror().

⚡ Quick Reference

ConstantTypical meaningExample scenario
ENOENTNo such file or directoryMissing file path
EACCESPermission deniedRead protected file
EINVALInvalid argumentBad function parameter
ENOMEMOut of memoryAllocation failed
Translate
strerror(errno)

Current error

Save first
int e = errno;

Before other calls

Copy
std::string msg

Keep message safe

Print fast
perror("open")

stderr helper

Examples Gallery

Compile with g++ strerror.cpp -std=c++17 -o strerror. These examples show how to turn numeric error codes into messages beginners can read and log.

📚 Getting Started

Translate a known error constant into readable text.

Example 1 — Basic strerror() with ENOENT

Simulate a “file not found” error and print the corresponding message.

C++
#include <iostream>
#include <cstring>
#include <cerrno>

int main() {
    errno = ENOENT; // No such file or directory

    const char* errorMessage = std::strerror(errno);

    std::cout << "Error code: " << errno << "\n";
    std::cout << "Message:    " << errorMessage << "\n";

    return 0;
}

How It Works

Setting errno = ENOENT mimics what the OS would do after a failed file operation. strerror maps that code to a localized description string.

Example 2 — Real fopen() Failure

Open a non-existent file and report the system error message.

C++
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>

int main() {
    std::FILE* file = std::fopen("missing_config.txt", "r");

    if (file == nullptr) {
        int err = errno;
        std::cout << "Could not open file: "
                  << std::strerror(err) << "\n";
        return 1;
    }

    std::fclose(file);
    return 0;
}

How It Works

When fopen returns nullptr, errno holds the reason. Saving it to err before any other library call keeps the correct code for strerror.

📈 Practical Patterns

Preserve errno, compare with perror, and store messages safely.

Example 3 — Save errno Before Other Calls

Demonstrate why copying errno immediately matters.

C++
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>

int main() {
    std::FILE* f = std::fopen("/no/access/here.txt", "r");
    if (f == nullptr) {
        int saved = errno;

        // Another call might change errno:
        std::strerror(saved);

        std::cout << "Saved errno: " << saved << "\n";
        std::cout << "Message:     " << std::strerror(saved) << "\n";
    }
    return 0;
}

How It Works

Always capture errno in a local int at the failure site. Later I/O, allocations, or even some error functions can overwrite the global value.

Example 4 — strerror() vs perror()

perror prints to stderr; strerror gives you the text to format yourself.

C++
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>

int main() {
    errno = EACCES; // Permission denied

    std::cout << "Using strerror:\n";
    std::cout << "  Access failed: " << std::strerror(errno) << "\n\n";

    std::cout << "Using perror (also writes to stderr):\n  ";
    std::perror("Access failed");

    return 0;
}

How It Works

Both use the same underlying messages. Choose strerror for logs, GUIs, or custom formatting; choose perror for quick terminal debugging.

Example 5 — Copy Message into std::string

Store the text safely for logging or returning from a function.

C++
#include <iostream>
#include <string>
#include <cstring>
#include <cerrno>

std::string describeError(int code) {
    return std::string(std::strerror(code));
}

int main() {
    errno = EINVAL;

    std::string msg = describeError(errno);
    std::cout << "Invalid operation: " << msg << "\n";

    return 0;
}

How It Works

Constructing a std::string copies the C-string immediately. The copy survives later calls to strerror and is easier to pass around in modern C++ code.

🚀 Common Use Cases

  • File and I/O errors — explain why fopen, read, or write failed.
  • User-facing error dialogs — show a readable reason instead of a raw number.
  • Logging and diagnostics — include system messages in log files.
  • Teaching and debugging — learn what constants like ENOENT mean in practice.
  • Wrapper functions — convert low-level failures into std::string exceptions or error types.

🧠 How strerror() Works

1

System call fails

A library function sets errno to a numeric code.

errno
2

Save the code

Copy errno to a local variable before other calls.

Capture
3

Lookup message

strerror(errnum) maps the number to a predefined text table.

Lookup
💬

Return C-string

Pointer to text such as “Permission denied”—copy it if you need it later.

📝 Notes

  • Include <cerrno> for errno and symbolic constants; include <cstring> for strerror.
  • The returned pointer must not be freed with delete or free.
  • Read errno immediately after failure—successful calls may leave it unchanged from an older error.
  • C++ exceptions (std::system_error) are the modern alternative for new code, but errno + strerror remains common in C APIs.
  • Error text may be translated according to system locale settings.

⚡ Optimization

strerror() is fast enough for error paths that run rarely. Avoid calling it inside tight loops on success paths. Cache the copied message once per failure instead of translating the same code repeatedly. For hot paths, log the numeric errno and translate offline if needed.

Conclusion

strerror() bridges the gap between numeric system errors and messages humans can understand. Save errno promptly, pass it to strerror, and copy the result when you need to keep or share the text.

Next, learn strlen() to measure C-string length—a building block for safe buffer sizing before calls like strcpy.

💡 Best Practices

✅ Do

  • Save errno to a local int right after failure
  • Copy the message into std::string for logs or returns
  • Check return values (nullptr, -1) before reading errno
  • Use meaningful context: "Config load failed: " + msg
  • Learn common codes: ENOENT, EACCES, EINVAL

❌ Don’t

  • Free or modify the pointer returned by strerror
  • Assume errno is zero on success for all functions
  • Call strerror twice and compare pointers expecting different strings
  • Rely on strerror in multi-threaded code without copying the text
  • Show raw errno numbers to end users without translation

Key Takeaways

Knowledge Unlocked

Five things to remember about strerror()

Use these points whenever system calls fail in your programs.

5
Core concepts
📝 02

char* Return

Library owned.

Return
💾 03

Save errno

Before other calls.

Safety
🚫 04

vs perror

String vs print.

Compare
📁 05

File I/O

fopen failures.

Use case

❓ Frequently Asked Questions

strerror() takes an integer error code (such as the value stored in errno) and returns a pointer to a human-readable description of that error, for example "No such file or directory" for ENOENT.
Include <cstring> for strerror() and <cerrno> for errno and symbolic constants like ENOENT and EINVAL. Some programs also include <iostream> for output.
Pass the error number: strerror(errno). Many system calls set errno when they fail; read errno immediately after the failing call, then pass it to strerror() before other library calls overwrite errno.
strerror() returns a message string you can store, log, or format. perror() prints a message directly to stderr, prefixed with your custom text. Use strerror() when you need the text in your own output; use perror() for quick console diagnostics.
No. The pointer refers to static storage managed by the C library. Do not call delete or free on it. Copy the text to a std::string if you need to keep it across later calls to strerror().
Classic strerror() may use a shared static buffer on some platforms, so concurrent calls can overwrite each other's text. For multi-threaded code, copy the result immediately into a std::string, or use platform-specific alternatives like strerror_r (POSIX) or strerror_s when available.
Did you know?

On POSIX systems, errno is a macro that expands to a thread-local integer. Each thread has its own error code, but the string returned by classic strerror() may still share static storage—copy the message if multiple threads format errors at the same time.

Continue the String Functions Series

Decode system errors with strerror(), then measure strings with strlen().

Next: strlen() →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful