Zum Hauptinhalt springen
ProdukteDesktop-WerkzeugeTASTECADZeichnungsprüfungTASTEFILESDateiverwaltungTASTEFTPDateiübertragungTASTESSHRemote-ArbeitsbereichTASTEZIPKomprimieren und EntpackenEntwicklerwerkzeugeTASTECODEIntegrierte Entwicklungsumgebung für RustTASTESTUDIOIntegrierte Entwicklungs- und TestumgebungTASTEETLDatenintegration (ETL)ServerTASTEREMOTERemote-Desktop-ServerTASTEGEOGeodatenserverTASTEMAILE-Mail-ArbeitsbereichErste SchritteDownloadsDokumentationKaufenAlle Produkte
Marktplatz
Neuigkeiten
TechnikNeuigkeitenEntwickler-News von heuteEntwicklerdokuProgrammiersprachenRustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDartWeb-Frontend-FrameworksNext.jsReactVue.js · NuxtSvelteKitAngularServer-FrameworksSpring BootDjangoFastAPIASP.NET CoreNestJS · ExpressApp- & Desktop-FrameworksTauriFlutterReact NativeElectronAlgorithmenAlgorithmus-GrundlagenKernalgorithmenFortgeschrittene AlgorithmenAlgorithmen für die Praxis
CommunityProjekteEntwicklungslogsPromptsProbleme mit KI-ToolsShowcaseCommunity-Leitfaden
ZusammenarbeitWissenstransferWebsite-AufbauDesktop-App-AufbauRelease- und ZahlungspipelineVertriebspartnerKontakt
DiensteRemote-DesktopIndividuelle Installationspakete
TASTEDEV
Produkte

Desktop-Werkzeuge

TASTECADKomplexe Zeichnungen, mühelos geöffnetTASTEFILESNur die Dateien, die zählen – in BestzeitTASTEFTPDer aufgeräumteste Weg für Ihre DateienTASTESSHDie stärkere Verbindung zu Ihren ServernTASTEZIPSchneller packen, sicherer entpacken

Entwicklerwerkzeuge

TASTECODERust-Apps bearbeiten, bauen, debuggen und testen – alles in einem FensterTASTESTUDIOVom Bearbeiten bis zu Remote-Tests und freigegebenen KI-KorrekturenTASTEETLDaten bewegen, die Werte im Blick

Server

TASTEREMOTEEin Remote-Desktop auf Ihrem eigenen ServerTASTEGEOEin GeoServer-kompatibler Geodatenserver, neu aufgebaut in RustTASTEMAILIhre E-Mail wieder in Ihrer Hand

Erste Schritte

DownloadsNeueste Versionen aller ProdukteDokuSo nutzen Sie jedes ProduktKaufenAbos und DauerlizenzenAlle ProdukteAlle Produkte im Überblick
Alle Produkte
MarktplatzNeuigkeiten
Technik

Neuigkeiten

Entwickler-News von heuteOffizielle Meldungen zu Sprachen, Frameworks, GitHub und KIEntwicklerdokuAnleitungen zu Sprachen, Frameworks und Algorithmen

Programmiersprachen

RustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDart

Frameworks

Web-Frontend-FrameworksNext.jsReactVue.js · NuxtSvelteKitAngular
Server-FrameworksSpring BootDjangoFastAPIASP.NET CoreNestJS · Express
App- & Desktop-FrameworksTauriFlutterReact NativeElectron

Algorithmen

Algorithmus-GrundlagenKomplexitätsanalyse · Sortieren · Suchen · Grundlegende Datenstrukturen · Bäume und HeapsKernalgorithmenGraphtraversierung · Kürzeste Wege und minimale Spannbäume · Dynamische Programmierung · Greedy-Algorithmen · Teile und herrsche · BacktrackingFortgeschrittene AlgorithmenZeichenkettenalgorithmen · Mathematik und Zahlentheorie · Bitmanipulation · Segmentbäume · Union-FindAlgorithmen für die PraxisStrategie für Coding-Interviews · LRU-Cache · Rate Limiting · Konsistentes Hashing
Alle Entwicklungsdokumente
Community
ProjekteEntwickler und Projekte entdeckenEntwicklungslogsEntscheidungen und ErkenntnissePromptsWiederverwendbare AnweisungenProbleme mit KI-ToolsProbleme und Workarounds für Claude, Codex, GeminiShowcaseFertige ErgebnisseCommunity-LeitfadenWie wir offen entwickeln
Zusammenarbeit
WissenstransferNative Apps mit Rust und eguiWebsite-Aufbau10 Sprachen, Konten, Dokumentation und DownloadsDesktop-App-AufbauRust und egui, ohne WebViewRelease- und ZahlungspipelineSignatur, MSI, deb, rpm, AppImage, PrüfsummenVertriebspartnerEmpfehlen und 30 % erhaltenKontaktEntwicklung, Partnerschaft, Investition
Dienste
Remote-DesktopIhren Computer im Browser erreichenIndividuelle InstallationspaketeNur nötige Funktionen, Einstellungen vorab
Kaufen
DE
한국어EnglishDeutschEspañolFrançaisItalianoPortuguês (Brasil)日本語简体中文繁體中文
Anmelden
Anmelden
TASTEDEV

Von kleinen Werkzeugen zu besserer Entwicklung.

support@tastedev.netTASTEDEV unterstützen
ProdukteProduktübersichtKaufenDokuDownloadsMarktplatzSupport
CommunityProjekteEntwicklungslogsPromptsProbleme mit KI-ToolsShowcase
RichtlinienDatenschutzerklärungNutzungsbedingungenAbo-BedingungenRückerstattungCommunity-Richtlinien
KontoAnmeldenRegistrieren
Besucher
Heute
012345678901234567890123456789012345678901234567890123456789
Gestern
012345678901234567890123456789012345678901234567890123456789
Aufrufe gesamt
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
Firma
GXSOFT
Vertretungsberechtigt
CHOI YOUNG GU
Handelsregisternummer
853-44-00368
Anschrift
9F V24, 351 Gyeongin-ro, Michuhol-gu, Incheon, Republic of Korea
Telefon
+82-10-4404-1523
E-Mail
whitecalvin@tastedev.net
Datenschutzbeauftragter
CHOI YOUNG GU

© 2026 TASTEDEVProduktinformationen basieren auf verifizierten Entwicklungsquellen.Veröffentlicht · wird verbessert

C-Dokumentation
C
Getting StartedSyntax BasicsTypes and DataModules and LibrariesErrors and TestingKey Concepts: Pointers and Memory
Diskussionen

C-Anleitung · 5/6

Errors and Testing

Dieses Kapitel ist vorerst nur auf Englisch verfügbar.

C has no exceptions. Functions report failure through return values and errno, and the caller must check every time. This chapter also covers assert, sanitizers, and lightweight unit testing.

Reporting errors with return codes

By convention, return 0 on success and a negative code on failure, passing the real result back through a pointer (an out-parameter). Pointer-returning functions signal failure with NULL.

#include <stdio.h>

enum { OK = 0, ERR_DIV_ZERO = -1, ERR_NULL = -2 };

int safe_divide(int a, int b, int *out) {
    if (out == NULL) return ERR_NULL;
    if (b == 0) return ERR_DIV_ZERO;
    *out = a / b;
    return OK;
}

int main(void) {
    int result;
    int rc = safe_divide(10, 0, &result);
    if (rc != OK) {
        fprintf(stderr, "division failed (code %d)\n", rc);
        return 1;
    }
    printf("%d\n", result);
    return 0;
}

Ignored return values are among the most common C bugs. If a call can fail, check it before using what it produced.

errno

Many standard library functions return a sentinel such as NULL, -1, or EOF on failure and store the reason in errno from <errno.h>. strerror(errno) and perror turn the code into a readable message.

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "usage: %s <file> [number]\n", argv[0]);
        return 1;
    }
    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", argv[1], strerror(errno));
        return 1;
    }
    fclose(fp);

    if (argc > 2) {
        char *end;
        errno = 0;                         /* reset before calling strtol */
        long n = strtol(argv[2], &end, 10);
        if (errno == ERANGE) {
            fprintf(stderr, "number out of range\n");
        } else if (end == argv[2] || *end != '\0') {
            fprintf(stderr, "not a number\n");
        } else {
            printf("n = %ld\n", n);
        }
    }
    return 0;
}

errno only means something after a failure, and successful calls do not reset it, so check the return value first. When the return value alone cannot signal an error, as with strtol, set errno = 0 beforehand. Avoid atoi, which cannot report bad input at all.

assert and defensive checks

assert from <assert.h> verifies an assumption that should always hold; if it fails, it prints the file and line and aborts. Defining NDEBUG compiles every assert away, so anything that can legitimately go wrong at run time, such as user input or file contents, needs a real check instead.

Fragen zu diesem Kapitel?
Vorheriges KapitelModules and LibrariesNächstes KapitelKey Concepts: Pointers and Memory
if
#include <assert.h>
#include <stdlib.h>
#include <string.h>

/* internal helper: caller obligations are checked with assert */
static void copy_ints(int *dst, const int *src, size_t n) {
    assert(dst != NULL && src != NULL);
    memcpy(dst, src, n * sizeof *dst);
}

/* public API: validate external input and report errors */
int *duplicate(const int *src, size_t n) {
    if (src == NULL || n == 0) return NULL;
    int *copy = malloc(n * sizeof *copy);
    if (copy == NULL) return NULL;        /* out of memory */
    copy_ints(copy, src, n);
    return copy;
}

When a function acquires several resources, a common idiom is to goto a single cleanup label on failure instead of repeating release code at every exit.

Sanitizers

Memory and overflow bugs often look harmless until they corrupt something far away. GCC and Clang sanitizers catch them the moment they happen.

  • AddressSanitizer (ASan) finds buffer overflows, use-after-free, double free, and leaks.
  • UndefinedBehaviorSanitizer (UBSan) finds signed overflow, division by zero, invalid shifts, and other undefined behavior.
gcc -std=c17 -g -O1 -fno-omit-frame-pointer \
    -fsanitize=address,undefined bug.c -o bug
./bug
// bug.c
#include <stdlib.h>
#include <limits.h>

int main(void) {
    int *a = malloc(4 * sizeof *a);
    a[4] = 1;              /* ASan: heap-buffer-overflow */
    free(a);

    int x = INT_MAX;
    x = x + 1;             /* UBSan: signed integer overflow */
    return x == 0;
}

The report points at the offending line and, for heap errors, the allocation site. Sanitized builds are slower, so use them for development and tests, not releases. MSVC supports ASan too, via /fsanitize=address.

A minimal unit test

The standard library ships no test framework, but a small test program gets you surprisingly far. Count failures and report through the exit status, and Make, CMake, and any CI system can use it directly.

// test_mathutil.c
#include <stdio.h>
#include "mathutil.h"

static int failures = 0;

#define CHECK(cond) do { \
    if (!(cond)) { \
        fprintf(stderr, "%s:%d: failed: %s\n", __FILE__, __LINE__, #cond); \
        failures++; \
    } \
} while (0)

int main(void) {
    CHECK(clamp(5, 0, 10) == 5);
    CHECK(clamp(-3, 0, 10) == 0);
    CHECK(clamp(42, 0, 10) == 10);
    printf("%s\n", failures ? "FAILED" : "OK");
    return failures ? 1 : 0;
}

With CMake, add enable_testing() and add_test(NAME mathutil COMMAND test_mathutil), then run ctest from the build directory. As the suite grows, consider frameworks such as Unity, cmocka, or Check, and build tests with sanitizers to catch memory errors in the same run.

Summary

  • Report errors through return values (0 for success, negative or NULL for failure) and always check them.
  • Read errno only after confirming a failure, and format it with strerror or perror.
  • assert checks programmer assumptions; validate external input with ordinary if statements.
  • Use -fsanitize=address,undefined during development to catch memory errors and undefined behavior.
  • Start with a tiny test program that reports through its exit status, and adopt a framework when you need one.

0 Kommentare

Top-KommentareNeueste zuerst

Anmelden · Melde dich an, um einen Kommentar zu schreiben.