亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

首頁(yè) 后端開發(fā) C++ 用 C 創(chuàng)建健壯的日志系統(tǒng)

用 C 創(chuàng)建健壯的日志系統(tǒng)

Nov 29, 2024 am 01:00 AM

Creating a Robust Logging System in C

創(chuàng)建強(qiáng)大的軟件需要做出深思熟慮的設(shè)計(jì)選擇,以簡(jiǎn)化代碼維護(hù)和擴(kuò)展功能。其中一個(gè)示例是在 C 應(yīng)用程序中實(shí)現(xiàn)日志記錄功能。日志記錄不僅僅是打印錯(cuò)誤消息;它是關(guān)于構(gòu)建一個(gè)支持調(diào)試、分析甚至跨平臺(tái)兼容性的結(jié)構(gòu)化系統(tǒng)。

在本文中,我們將受現(xiàn)實(shí)場(chǎng)景的啟發(fā),探索如何使用設(shè)計(jì)模式和最佳實(shí)踐逐步構(gòu)建日志系統(tǒng)。最后,您將對(duì)用 C 語(yǔ)言創(chuàng)建靈活且可擴(kuò)展的日志系統(tǒng)有深入的了解。

目錄

  1. 日志記錄的需要
  2. 組織日志文件
  3. 創(chuàng)建中央日志功能
  4. 實(shí)現(xiàn)軟件模塊過(guò)濾器
  5. 添加條件日志記錄
  6. 正確管理資源
  7. 確保線程安全
  8. 外部和動(dòng)態(tài)配置
  9. 自定義日志格式
  10. 內(nèi)部錯(cuò)誤處理
  11. 性能和效率
  12. 安全最佳實(shí)踐
  13. 與日志記錄工具集成
  14. 測(cè)試和驗(yàn)證
  15. 跨平臺(tái)文件記錄
  16. 把一切都包起來(lái)
  17. 額外

日志記錄的需要

想象一下維護(hù)部署在遠(yuǎn)程站點(diǎn)的軟件系統(tǒng)。每當(dāng)出現(xiàn)問(wèn)題時(shí),您必須親自出差來(lái)調(diào)試問(wèn)題。隨著部署在地理上的擴(kuò)展,這種設(shè)置很快就會(huì)變得不切實(shí)際。記錄可以挽救局面。

日志記錄提供了執(zhí)行過(guò)程中關(guān)鍵點(diǎn)的系統(tǒng)內(nèi)部狀態(tài)的詳細(xì)記錄。通過(guò)檢查日志文件,開發(fā)人員可以診斷和解決問(wèn)題,而無(wú)需直接重現(xiàn)問(wèn)題。這對(duì)于難以在受控環(huán)境中重新創(chuàng)建的偶發(fā)錯(cuò)誤特別有用。

日志記錄的價(jià)值在多線程應(yīng)用程序中變得更加明顯,其中錯(cuò)誤可能取決于時(shí)間和競(jìng)爭(zhēng)條件。在沒(méi)有日志的情況下調(diào)試這些問(wèn)題需要大量的努力和專門的工具,而這些工具可能并不總是可用。日志提供了所發(fā)生事件的快照,有助于查明根本原因。

然而,日志記錄不僅僅是一個(gè)簡(jiǎn)單的功能——它是一個(gè)系統(tǒng)。實(shí)施不當(dāng)?shù)娜罩居涗洐C(jī)制可能會(huì)導(dǎo)致性能問(wèn)題、安全漏洞和不可維護(hù)的代碼。因此,在設(shè)計(jì)日志系統(tǒng)時(shí),遵循結(jié)構(gòu)化方法和模式至關(guān)重要。

組織記錄文件

正確的文件組織對(duì)于保持代碼庫(kù)在增長(zhǎng)時(shí)的可維護(hù)性至關(guān)重要。日志記錄作為一項(xiàng)獨(dú)特的功能,應(yīng)該隔離到自己的模塊中,以便輕松定位和修改,而不影響代碼的不相關(guān)部分。

頭文件(logger.h):

#ifndef LOGGER_H
#define LOGGER_H

#include <stdio.h>
#include <time.h>

// Function prototypes
void log_message(const char* text);

#endif // LOGGER_H

實(shí)現(xiàn)文件(logger.c):

#include "logger.h"

void log_message(const char* text) {
    if (!text) {
        fprintf(stderr, "Invalid log message\n");
        return;
    }
    time_t now = time(NULL);
    printf("[%s] %s\n", ctime(&now), text);
}

用法(main.c):

#include "logger.h"

int main() {
    log_message("Application started");
    log_message("Performing operation...");
    log_message("Operation completed.");
    return 0;
}

編譯并運(yùn)行:

要編譯并運(yùn)行該示例,請(qǐng)?jiān)诮K端中使用以下命令:

gcc -o app main.c logger.c
./app

預(yù)期輸出:

[Mon Sep 27 14:00:00 2021
] Application started
[Mon Sep 27 14:00:00 2021
] Performing operation...
[Mon Sep 27 14:00:00 2021
] Operation completed.

第一步是創(chuàng)建一個(gè)用于日志記錄的專用目錄。該目錄應(yīng)包含所有相關(guān)的實(shí)現(xiàn)文件。例如,logger.c 可以包含日志系統(tǒng)的核心邏輯,而 logger_test.c 可以保存單元測(cè)試。將相關(guān)文件放在一起可以提高開發(fā)團(tuán)隊(duì)內(nèi)的清晰度和協(xié)作性。

此外,日志記錄接口應(yīng)通過(guò)頭文件(例如 logger.h)公開,并放置在適當(dāng)?shù)哪夸浿?,例?include/ 或與源文件相同的目錄。這確保了需要日志記錄功能的其他模塊可以輕松訪問(wèn)它。將頭文件與實(shí)現(xiàn)文件分開還支持封裝,向日志記錄 API 的用戶隱藏實(shí)現(xiàn)細(xì)節(jié)。

最后,對(duì)目錄和文件采用一致的命名約定可以進(jìn)一步增強(qiáng)可維護(hù)性。例如,使用 logger.h 和 logger.c 可以清楚地表明這些文件屬于日志記錄模塊。避免將不相關(guān)的代碼混合到日志記錄模塊中,因?yàn)檫@違背了模塊化的目的。

創(chuàng)建中央日志記錄功能

任何日志系統(tǒng)的核心都有一個(gè)處理核心操作的核心功能:記錄日志消息。此功能的設(shè)計(jì)應(yīng)考慮簡(jiǎn)單性和可擴(kuò)展性,以支持未來(lái)的增強(qiáng)功能,而無(wú)需進(jìn)行重大更改。

實(shí)現(xiàn)(logger.c):

#include "logger.h"
#include <stdio.h>
#include <time.h>
#include <assert.h>

#define BUFFER_SIZE 256
static_assert(BUFFER_SIZE >= 64, "Buffer size is too small");

void log_message(const char* text) {
    char buffer[BUFFER_SIZE];
    time_t now = time(NULL);

    if (!text) {
        fprintf(stderr, "Error: Null message passed to log_message\n");
        return;
    }

    snprintf(buffer, BUFFER_SIZE, "[%s] %s", ctime(&now), text);
    printf("%s", buffer);
}

注意:使用 static_assert 需要 C11 或更高版本。確保您的編譯器支持此標(biāo)準(zhǔn)。

基本的日志記錄功能可以通過(guò)將消息打印到標(biāo)準(zhǔn)輸出來(lái)啟動(dòng)。向每個(gè)日志條目添加時(shí)間戳可以通過(guò)提供時(shí)間上下文來(lái)提高其實(shí)用性。例如,日志可以幫助識(shí)別特定錯(cuò)誤何時(shí)發(fā)生或事件如何隨著時(shí)間的推移展開。

為了保持日志記錄模塊無(wú)狀態(tài),請(qǐng)避免在函數(shù)調(diào)用之間保留任何內(nèi)部狀態(tài)。這種設(shè)計(jì)選擇簡(jiǎn)化了實(shí)現(xiàn),并確保模塊在多線程環(huán)境中無(wú)縫工作。無(wú)狀態(tài)模塊也更容易測(cè)試和調(diào)試,因?yàn)樗鼈兊男袨椴灰蕾囉谙惹暗慕换ァ?/p>

設(shè)計(jì)日志記錄功能時(shí)考慮錯(cuò)誤處理。例如,如果將 NULL 指針作為日志消息傳遞,會(huì)發(fā)生什么情況?遵循“武士原則”,該函數(shù)應(yīng)該要么優(yōu)雅地處理這個(gè)問(wèn)題,要么立即失敗,從而使調(diào)試更容易。

實(shí)施軟件模塊過(guò)濾器

隨著應(yīng)用程序變得越來(lái)越復(fù)雜,它們的日志輸出可能會(huì)變得難以承受。如果沒(méi)有過(guò)濾器,來(lái)自不相關(guān)模塊的日志可能會(huì)淹沒(méi)控制臺(tái),從而難以關(guān)注相關(guān)信息。實(shí)施過(guò)濾器可確保僅記錄所需的日志。

為了實(shí)現(xiàn)這一點(diǎn),引入一種機(jī)制來(lái)跟蹤啟用的模塊。這可以像全局列表一樣簡(jiǎn)單,也可以像動(dòng)態(tài)分配的哈希表一樣復(fù)雜。該列表存儲(chǔ)模塊名稱,并且僅處理來(lái)自這些模塊的日志。

過(guò)濾是通過(guò)在日志記錄函數(shù)中添加模塊參數(shù)來(lái)實(shí)現(xiàn)的。在寫入日志之前,該函數(shù)會(huì)檢查模塊是否已啟用。如果不是,它會(huì)跳過(guò)日志條目。這種方法使日志記錄輸出簡(jiǎn)潔并集中于感興趣的領(lǐng)域。這是過(guò)濾的示例實(shí)現(xiàn):

頭文件(logger.h):

#ifndef LOGGER_H
#define LOGGER_H

#include <stdio.h>
#include <time.h>

// Function prototypes
void log_message(const char* text);

#endif // LOGGER_H

實(shí)現(xiàn)文件(logger.c):

#include "logger.h"

void log_message(const char* text) {
    if (!text) {
        fprintf(stderr, "Invalid log message\n");
        return;
    }
    time_t now = time(NULL);
    printf("[%s] %s\n", ctime(&now), text);
}

此實(shí)現(xiàn)在簡(jiǎn)單性和功能性之間取得了平衡,為特定于模塊的日志記錄提供了堅(jiān)實(shí)的起點(diǎn)。

添加條件日志記錄

條件日志記錄對(duì)于創(chuàng)建適應(yīng)不同環(huán)境或運(yùn)行時(shí)條件的靈活系統(tǒng)至關(guān)重要。例如,在開發(fā)過(guò)程中,您可能需要詳細(xì)的調(diào)試日志來(lái)跟蹤應(yīng)用程序行為。在生產(chǎn)中,您可能更愿意僅記錄警告和錯(cuò)誤,以最大限度地減少性能開銷。

實(shí)現(xiàn)此目的的一種方法是引入日志級(jí)別。常見級(jí)別包括調(diào)試、信息、警告和錯(cuò)誤。日志記錄功能可以為日志級(jí)別添加一個(gè)附加參數(shù),只有當(dāng)日志級(jí)別達(dá)到或超過(guò)當(dāng)前閾值時(shí)才會(huì)記錄日志。這種方法可確保過(guò)濾掉不相關(guān)的消息,從而保持日志簡(jiǎn)潔且有用。

為了使其可配置,您可以使用全局變量來(lái)存儲(chǔ)日志級(jí)別閾值。然后,應(yīng)用程序可以動(dòng)態(tài)調(diào)整此閾值,例如通過(guò)配置文件或運(yùn)行時(shí)命令。

頭文件(logger.h):

#include "logger.h"

int main() {
    log_message("Application started");
    log_message("Performing operation...");
    log_message("Operation completed.");
    return 0;
}

實(shí)現(xiàn)文件(logger.c):

gcc -o app main.c logger.c
./app

此實(shí)現(xiàn)可以輕松控制日志記錄的詳細(xì)程度。例如,您可以在故障排除會(huì)話期間將日志級(jí)別設(shè)置為 DEBUG,并在生產(chǎn)中將其恢復(fù)為 WARNING。

正確管理資源

適當(dāng)?shù)馁Y源管理至關(guān)重要,尤其是在處理文件操作或多個(gè)日志記錄目的地時(shí)。未能關(guān)閉文件或釋放分配的內(nèi)存可能會(huì)導(dǎo)致資源泄漏,隨著時(shí)間的推移會(huì)降低系統(tǒng)性能。

確保為記錄而打開的任何文件在不再需要時(shí)正確關(guān)閉。這可以通過(guò)實(shí)現(xiàn)初始化和關(guān)閉日志系統(tǒng)的函數(shù)來(lái)實(shí)現(xiàn)。

實(shí)現(xiàn)(logger.c):

#ifndef LOGGER_H
#define LOGGER_H

#include <stdio.h>
#include <time.h>

// Function prototypes
void log_message(const char* text);

#endif // LOGGER_H

用法(main.c):

#include "logger.h"

void log_message(const char* text) {
    if (!text) {
        fprintf(stderr, "Invalid log message\n");
        return;
    }
    time_t now = time(NULL);
    printf("[%s] %s\n", ctime(&now), text);
}

編譯并運(yùn)行:

#include "logger.h"

int main() {
    log_message("Application started");
    log_message("Performing operation...");
    log_message("Operation completed.");
    return 0;
}

這會(huì)將日志消息寫入 application.log。通過(guò)提供 init_logging 和 close_logging 函數(shù),您可以讓應(yīng)用程序控制日志記錄資源的生命周期,防止泄漏和訪問(wèn)問(wèn)題。

確保線程安全

在多線程應(yīng)用程序中,日志記錄函數(shù)必須是線程安全的,以防止競(jìng)爭(zhēng)條件并確保日志消息不會(huì)交錯(cuò)或損壞。

實(shí)現(xiàn)線程安全的一種方法是使用互斥體或其他同步機(jī)制。

實(shí)現(xiàn)(logger.c):

gcc -o app main.c logger.c
./app

多線程環(huán)境中的使用(main.c):

[Mon Sep 27 14:00:00 2021
] Application started
[Mon Sep 27 14:00:00 2021
] Performing operation...
[Mon Sep 27 14:00:00 2021
] Operation completed.

編譯并運(yùn)行:

#include "logger.h"
#include <stdio.h>
#include <time.h>
#include <assert.h>

#define BUFFER_SIZE 256
static_assert(BUFFER_SIZE >= 64, "Buffer size is too small");

void log_message(const char* text) {
    char buffer[BUFFER_SIZE];
    time_t now = time(NULL);

    if (!text) {
        fprintf(stderr, "Error: Null message passed to log_message\n");
        return;
    }

    snprintf(buffer, BUFFER_SIZE, "[%s] %s", ctime(&now), text);
    printf("%s", buffer);
}

這可以確保來(lái)自不同線程的日志不會(huì)相互干擾,從而保持日志消息的完整性。

外部和動(dòng)態(tài)配置

允許在外部設(shè)置日志配置增強(qiáng)了靈活性。日志級(jí)別、啟用的模塊和目標(biāo)等配置可以從配置文件加載或通過(guò)命令行參數(shù)設(shè)置。

配置文件(config.cfg):

#ifndef LOGGER_H
#define LOGGER_H

#include <stdbool.h>

void enable_module(const char* module);
void disable_module(const char* module);
void log_message(const char* module, const char* text);

#endif // LOGGER_H

實(shí)現(xiàn)(logger.c):

#include "logger.h"
#include <stdio.h>
#include <string.h>

#define MAX_MODULES 10
#define MODULE_NAME_LENGTH 20

static char enabled_modules[MAX_MODULES][MODULE_NAME_LENGTH];

void enable_module(const char* module) {
    for (int i = 0; i < MAX_MODULES; i++) {
        if (enabled_modules[i][0] == '<pre class="brush:php;toolbar:false">#ifndef LOGGER_H
#define LOGGER_H

typedef enum { DEBUG, INFO, WARNING, ERROR } LogLevel;

void set_log_level(LogLevel level);
void log_message(LogLevel level, const char* module, const char* text);

#endif // LOGGER_H
') { strncpy(enabled_modules[i], module, MODULE_NAME_LENGTH - 1); enabled_modules[i][MODULE_NAME_LENGTH - 1] = '
#include "logger.h"
#include <stdio.h>
#include <time.h>
#include <string.h>

static LogLevel current_log_level = INFO;

void set_log_level(LogLevel level) {
    current_log_level = level;
}

void log_message(LogLevel level, const char* module, const char* text) {
    if (level < current_log_level) {
        return;
    }
    const char* level_strings[] = { "DEBUG", "INFO", "WARNING", "ERROR" };
    time_t now = time(NULL);
    printf("[%s][%s][%s] %s\n", ctime(&now), level_strings[level], module, text);
}
'; break; } } } void disable_module(const char* module) { for (int i = 0; i < MAX_MODULES; i++) { if (strcmp(enabled_modules[i], module) == 0) { enabled_modules[i][0] = '
#include "logger.h"
#include <stdio.h>
#include <stdlib.h>

static FILE* log_file = NULL;

void init_logging(const char* filename) {
    if (filename) {
        log_file = fopen(filename, "a");
        if (!log_file) {
            fprintf(stderr, "Failed to open log file: %s\n", filename);
            exit(EXIT_FAILURE);
        }
    } else {
        log_file = stdout; // Default to standard output
    }
}

void close_logging() {
    if (log_file && log_file != stdout) {
        fclose(log_file);
        log_file = NULL;
    }
}

void log_message(const char* text) {
    if (!log_file) {
        fprintf(stderr, "Logging not initialized.\n");
        return;
    }
    time_t now = time(NULL);
    fprintf(log_file, "[%s] %s\n", ctime(&now), text);
    fflush(log_file); // Ensure the message is written immediately
}
'; break; } } } static int is_module_enabled(const char* module) { for (int i = 0; i < MAX_MODULES; i++) { if (strcmp(enabled_modules[i], module) == 0) { return 1; } } return 0; } void log_message(const char* module, const char* text) { if (!is_module_enabled(module)) { return; } time_t now = time(NULL); printf("[%s][%s] %s\n", ctime(&now), module, text); }

用法(main.c):

#include "logger.h"

int main() {
    init_logging("application.log");

    log_message("Application started");
    log_message("Performing operation...");
    log_message("Operation completed.");

    close_logging();
    return 0;
}

編譯并運(yùn)行:

gcc -o app main.c logger.c
./app

通過(guò)實(shí)現(xiàn)動(dòng)態(tài)配置,您可以調(diào)整日志記錄行為而無(wú)需重新編譯應(yīng)用程序,這在生產(chǎn)環(huán)境中特別有用。

自定義日志格式

自定義日志消息的格式可以使其信息更豐富且更易于解析,尤其是在與日志分析工具集成時(shí)。

實(shí)現(xiàn)(logger.c):

#include "logger.h"
#include <pthread.h>

static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;

void log_message(const char* text) {
    pthread_mutex_lock(&log_mutex);
    // Existing logging code
    if (!log_file) {
        fprintf(stderr, "Logging not initialized.\n");
        pthread_mutex_unlock(&log_mutex);
        return;
    }
    time_t now = time(NULL);
    fprintf(log_file, "[%s] %s\n", ctime(&now), text);
    fflush(log_file);
    pthread_mutex_unlock(&log_mutex);
}

示例輸出:

#include "logger.h"
#include <pthread.h>

void* thread_function(void* arg) {
    char* thread_name = (char*)arg;
    for (int i = 0; i < 5; i++) {
        char message[50];
        sprintf(message, "%s: Operation %d", thread_name, i + 1);
        log_message(message);
    }
    return NULL;
}

int main() {
    init_logging("application.log");

    pthread_t thread1, thread2;

    pthread_create(&thread1, NULL, thread_function, "Thread1");
    pthread_create(&thread2, NULL, thread_function, "Thread2");

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    close_logging();
    return 0;
}

對(duì)于結(jié)構(gòu)化日志記錄,請(qǐng)考慮以 JSON 格式輸出日志:

gcc -pthread -o app main.c logger.c
./app

這種格式適合日志管理工具解析。

內(nèi)部錯(cuò)誤處理

日志系統(tǒng)本身可能會(huì)遇到錯(cuò)誤,例如無(wú)法打開文件或資源分配問(wèn)題。妥善處理這些錯(cuò)誤并向開發(fā)人員提供反饋非常重要。

實(shí)現(xiàn)(logger.c):

#ifndef LOGGER_H
#define LOGGER_H

#include <stdio.h>
#include <time.h>

// Function prototypes
void log_message(const char* text);

#endif // LOGGER_H

通過(guò)在使用前檢查資源狀態(tài)并提供有意義的錯(cuò)誤消息,您可以防止崩潰并幫助排除日志系統(tǒng)本身的問(wèn)題。

性能和效率

日志記錄會(huì)影響應(yīng)用程序性能,尤其是在日志記錄范圍廣泛或同步執(zhí)行的情況下。為了緩解這種情況,請(qǐng)考慮緩沖日志或異步執(zhí)行日志記錄操作等技術(shù)。

異步日志實(shí)現(xiàn)(logger.c):

#include "logger.h"

void log_message(const char* text) {
    if (!text) {
        fprintf(stderr, "Invalid log message\n");
        return;
    }
    time_t now = time(NULL);
    printf("[%s] %s\n", ctime(&now), text);
}

用法(main.c):

#include "logger.h"

int main() {
    log_message("Application started");
    log_message("Performing operation...");
    log_message("Operation completed.");
    return 0;
}

使用異步日志記錄可以減少主應(yīng)用程序線程在日志記錄上花費(fèi)的時(shí)間,從而提高整體性能。

安全最佳實(shí)踐

日志可能會(huì)無(wú)意中暴露敏感信息,例如密碼或個(gè)人數(shù)據(jù)。避免記錄此類信息并保護(hù)日志文件免遭未經(jīng)授權(quán)的訪問(wèn)至關(guān)重要。

實(shí)現(xiàn)(logger.c):

gcc -o app main.c logger.c
./app

設(shè)置文件權(quán)限:

[Mon Sep 27 14:00:00 2021
] Application started
[Mon Sep 27 14:00:00 2021
] Performing operation...
[Mon Sep 27 14:00:00 2021
] Operation completed.

推薦:

  • 清理輸入:確保日志消息中不包含敏感數(shù)據(jù)。
  • 訪問(wèn)控制:對(duì)日志文件設(shè)置適當(dāng)?shù)臋?quán)限以限制訪問(wèn)。
  • 加密:如果日志文件包含敏感信息,請(qǐng)考慮對(duì)其進(jìn)行加密。
  • 日志輪換:實(shí)施日志輪換以防止日志無(wú)限增長(zhǎng)并管理暴露。

通過(guò)遵循這些做法,您可以增強(qiáng)應(yīng)用程序的安全性并遵守?cái)?shù)據(jù)保護(hù)法規(guī)。

與日志記錄工具集成

現(xiàn)代應(yīng)用程序通常與外部日志記錄工具和服務(wù)集成,以實(shí)現(xiàn)更好的日志管理和分析。

系統(tǒng)日志集成(logger.c):

#include "logger.h"
#include <stdio.h>
#include <time.h>
#include <assert.h>

#define BUFFER_SIZE 256
static_assert(BUFFER_SIZE >= 64, "Buffer size is too small");

void log_message(const char* text) {
    char buffer[BUFFER_SIZE];
    time_t now = time(NULL);

    if (!text) {
        fprintf(stderr, "Error: Null message passed to log_message\n");
        return;
    }

    snprintf(buffer, BUFFER_SIZE, "[%s] %s", ctime(&now), text);
    printf("%s", buffer);
}

用法(main.c):

#ifndef LOGGER_H
#define LOGGER_H

#include <stdbool.h>

void enable_module(const char* module);
void disable_module(const char* module);
void log_message(const char* module, const char* text);

#endif // LOGGER_H

遠(yuǎn)程記錄服務(wù):

要將日志發(fā)送到 Graylog 或 Elasticsearch 等遠(yuǎn)程服務(wù),您可以使用網(wǎng)絡(luò)套接字或?qū)S脦?kù)。

使用套接字的示例(logger.c):

#include "logger.h"
#include <stdio.h>
#include <string.h>

#define MAX_MODULES 10
#define MODULE_NAME_LENGTH 20

static char enabled_modules[MAX_MODULES][MODULE_NAME_LENGTH];

void enable_module(const char* module) {
    for (int i = 0; i < MAX_MODULES; i++) {
        if (enabled_modules[i][0] == '<pre class="brush:php;toolbar:false">#ifndef LOGGER_H
#define LOGGER_H

typedef enum { DEBUG, INFO, WARNING, ERROR } LogLevel;

void set_log_level(LogLevel level);
void log_message(LogLevel level, const char* module, const char* text);

#endif // LOGGER_H
') { strncpy(enabled_modules[i], module, MODULE_NAME_LENGTH - 1); enabled_modules[i][MODULE_NAME_LENGTH - 1] = '
#include "logger.h"
#include <stdio.h>
#include <time.h>
#include <string.h>

static LogLevel current_log_level = INFO;

void set_log_level(LogLevel level) {
    current_log_level = level;
}

void log_message(LogLevel level, const char* module, const char* text) {
    if (level < current_log_level) {
        return;
    }
    const char* level_strings[] = { "DEBUG", "INFO", "WARNING", "ERROR" };
    time_t now = time(NULL);
    printf("[%s][%s][%s] %s\n", ctime(&now), level_strings[level], module, text);
}
'; break; } } } void disable_module(const char* module) { for (int i = 0; i < MAX_MODULES; i++) { if (strcmp(enabled_modules[i], module) == 0) { enabled_modules[i][0] = '
#include "logger.h"
#include <stdio.h>
#include <stdlib.h>

static FILE* log_file = NULL;

void init_logging(const char* filename) {
    if (filename) {
        log_file = fopen(filename, "a");
        if (!log_file) {
            fprintf(stderr, "Failed to open log file: %s\n", filename);
            exit(EXIT_FAILURE);
        }
    } else {
        log_file = stdout; // Default to standard output
    }
}

void close_logging() {
    if (log_file && log_file != stdout) {
        fclose(log_file);
        log_file = NULL;
    }
}

void log_message(const char* text) {
    if (!log_file) {
        fprintf(stderr, "Logging not initialized.\n");
        return;
    }
    time_t now = time(NULL);
    fprintf(log_file, "[%s] %s\n", ctime(&now), text);
    fflush(log_file); // Ensure the message is written immediately
}
'; break; } } } static int is_module_enabled(const char* module) { for (int i = 0; i < MAX_MODULES; i++) { if (strcmp(enabled_modules[i], module) == 0) { return 1; } } return 0; } void log_message(const char* module, const char* text) { if (!is_module_enabled(module)) { return; } time_t now = time(NULL); printf("[%s][%s] %s\n", ctime(&now), module, text); }

用法(main.c):

#include "logger.h"

int main() {
    init_logging("application.log");

    log_message("Application started");
    log_message("Performing operation...");
    log_message("Operation completed.");

    close_logging();
    return 0;
}

與外部工具集成可以提供集中日志管理、實(shí)時(shí)監(jiān)控和警報(bào)等高級(jí)功能。

測(cè)試和驗(yàn)證

徹底的測(cè)試確保日志系統(tǒng)在各種條件下都能正常運(yùn)行。

單元測(cè)試示例(test_logger.c):

gcc -o app main.c logger.c
./app

編譯并運(yùn)行測(cè)試:

#include "logger.h"
#include <pthread.h>

static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;

void log_message(const char* text) {
    pthread_mutex_lock(&log_mutex);
    // Existing logging code
    if (!log_file) {
        fprintf(stderr, "Logging not initialized.\n");
        pthread_mutex_unlock(&log_mutex);
        return;
    }
    time_t now = time(NULL);
    fprintf(log_file, "[%s] %s\n", ctime(&now), text);
    fflush(log_file);
    pthread_mutex_unlock(&log_mutex);
}

測(cè)試策略:

  • 單元測(cè)試:驗(yàn)證各個(gè)函數(shù)。
  • 壓力測(cè)試:模擬高頻日志記錄。
  • 多線程測(cè)試: 同時(shí)從多個(gè)線程記錄。
  • 故障注入:模擬磁盤已滿或網(wǎng)絡(luò)故障等錯(cuò)誤。

通過(guò)嚴(yán)格測(cè)試日志系統(tǒng),您可以在問(wèn)題影響生產(chǎn)環(huán)境之前識(shí)別并修復(fù)問(wèn)題。

跨平臺(tái)文件記錄

跨平臺(tái)兼容性是現(xiàn)代軟件的必要條件。雖然前面的示例在基于 Unix 的系統(tǒng)上運(yùn)行良好,但由于文件處理 API 的差異,它們可能無(wú)法在 Windows 上運(yùn)行。為了解決這個(gè)問(wèn)題,您需要一個(gè)跨平臺(tái)的日志機(jī)制。

實(shí)現(xiàn)(logger.c):

#ifndef LOGGER_H
#define LOGGER_H

#include <stdio.h>
#include <time.h>

// Function prototypes
void log_message(const char* text);

#endif // LOGGER_H

用法(logger.c):

#include "logger.h"

void log_message(const char* text) {
    if (!text) {
        fprintf(stderr, "Invalid log message\n");
        return;
    }
    time_t now = time(NULL);
    printf("[%s] %s\n", ctime(&now), text);
}

通過(guò)隔離特定于平臺(tái)的詳細(xì)信息,您可以確保主要日志記錄邏輯保持干凈且一致。

總結(jié)一切

設(shè)計(jì)日志系統(tǒng)乍一看似乎是一項(xiàng)簡(jiǎn)單的任務(wù),但正如我們所見,它涉及許多影響功能、性能和可維護(hù)性的決策。通過(guò)使用設(shè)計(jì)模式和結(jié)構(gòu)化方法,您可以創(chuàng)建一個(gè)健壯、可擴(kuò)展且易于集成的日志系統(tǒng)。

從組織文件到實(shí)現(xiàn)跨平臺(tái)兼容性,每一步都建立在前一步的基礎(chǔ)上,形成一個(gè)有凝聚力的整體。系統(tǒng)可以按模塊過(guò)濾日志,通過(guò)日志級(jí)別調(diào)整詳細(xì)程度,支持多個(gè)目的地,并正確處理資源。它確保線程安全,允許外部配置,支持自定義格式,并遵守安全最佳實(shí)踐。

通過(guò)采用無(wú)狀態(tài)設(shè)計(jì)、動(dòng)態(tài)接口抽象層等模式,您可以避免常見的陷阱并使您的代碼庫(kù)面向未來(lái)。無(wú)論您是在開發(fā)小型實(shí)用程序還是大型應(yīng)用程序,這些原則都是非常寶貴的。

您在構(gòu)建精心設(shè)計(jì)的日志系統(tǒng)方面投入的精力會(huì)得到回報(bào),減少調(diào)試時(shí)間,更好地洞察應(yīng)用程序行為,并提高利益相關(guān)者的滿意度。有了這個(gè)基礎(chǔ),您現(xiàn)在就可以處理最復(fù)雜項(xiàng)目的日志記錄需求。

額外:增強(qiáng)日志系統(tǒng)

在這個(gè)額外的部分中,我們將解決之前確定的一些需要改進(jìn)的領(lǐng)域,以增強(qiáng)我們構(gòu)建的日志系統(tǒng)。我們將專注于改進(jìn)代碼一致性、改進(jìn)錯(cuò)誤處理、闡明復(fù)雜概念以及擴(kuò)展測(cè)試和驗(yàn)證。每個(gè)主題都包含介紹性文字、可編譯的實(shí)際示例以及供進(jìn)一步學(xué)習(xí)的外部參考資料。

1. 代碼一致性和格式

一致的代碼格式和命名約定提高了可讀性和可維護(hù)性。我們將使用 Snake_case 標(biāo)準(zhǔn)化變量和函數(shù)名稱,這在 C 編程中很常見。

更新的實(shí)現(xiàn) (logger.h):

#ifndef LOGGER_H
#define LOGGER_H

#include <stdio.h>
#include <time.h>

// Function prototypes
void log_message(const char* text);

#endif // LOGGER_H

更新的實(shí)現(xiàn) (logger.c):

#include "logger.h"

void log_message(const char* text) {
    if (!text) {
        fprintf(stderr, "Invalid log message\n");
        return;
    }
    time_t now = time(NULL);
    printf("[%s] %s\n", ctime(&now), text);
}

更新用法(main.c):

#include "logger.h"

int main() {
    log_message("Application started");
    log_message("Performing operation...");
    log_message("Operation completed.");
    return 0;
}

編譯并運(yùn)行:

gcc -o app main.c logger.c
./app

外部參考:

  • GNU 編碼標(biāo)準(zhǔn):命名約定
  • Linux 內(nèi)核編碼風(fēng)格

2. 改進(jìn)的錯(cuò)誤處理

強(qiáng)大的錯(cuò)誤處理功能確保應(yīng)用程序能夠優(yōu)雅地處理意外情況。

增強(qiáng)的錯(cuò)誤檢查(logger.c):

[Mon Sep 27 14:00:00 2021
] Application started
[Mon Sep 27 14:00:00 2021
] Performing operation...
[Mon Sep 27 14:00:00 2021
] Operation completed.

外部參考:

  • C 中的錯(cuò)誤處理
  • C 語(yǔ)言的斷言

3. 澄清異步日志記錄

異步日志記錄通過(guò)將日志記錄過(guò)程與主應(yīng)用程序流程分離來(lái)提高性能。這里有一個(gè)實(shí)際例子的詳細(xì)解釋。

實(shí)現(xiàn)(logger.c):

#include "logger.h"
#include <stdio.h>
#include <time.h>
#include <assert.h>

#define BUFFER_SIZE 256
static_assert(BUFFER_SIZE >= 64, "Buffer size is too small");

void log_message(const char* text) {
    char buffer[BUFFER_SIZE];
    time_t now = time(NULL);

    if (!text) {
        fprintf(stderr, "Error: Null message passed to log_message\n");
        return;
    }

    snprintf(buffer, BUFFER_SIZE, "[%s] %s", ctime(&now), text);
    printf("%s", buffer);
}

用法(main.c):

#ifndef LOGGER_H
#define LOGGER_H

#include <stdbool.h>

void enable_module(const char* module);
void disable_module(const char* module);
void log_message(const char* module, const char* text);

#endif // LOGGER_H

編譯并運(yùn)行:

#include "logger.h"
#include <stdio.h>
#include <string.h>

#define MAX_MODULES 10
#define MODULE_NAME_LENGTH 20

static char enabled_modules[MAX_MODULES][MODULE_NAME_LENGTH];

void enable_module(const char* module) {
    for (int i = 0; i < MAX_MODULES; i++) {
        if (enabled_modules[i][0] == '<pre class="brush:php;toolbar:false">#ifndef LOGGER_H
#define LOGGER_H

typedef enum { DEBUG, INFO, WARNING, ERROR } LogLevel;

void set_log_level(LogLevel level);
void log_message(LogLevel level, const char* module, const char* text);

#endif // LOGGER_H
') { strncpy(enabled_modules[i], module, MODULE_NAME_LENGTH - 1); enabled_modules[i][MODULE_NAME_LENGTH - 1] = '
#include "logger.h"
#include <stdio.h>
#include <time.h>
#include <string.h>

static LogLevel current_log_level = INFO;

void set_log_level(LogLevel level) {
    current_log_level = level;
}

void log_message(LogLevel level, const char* module, const char* text) {
    if (level < current_log_level) {
        return;
    }
    const char* level_strings[] = { "DEBUG", "INFO", "WARNING", "ERROR" };
    time_t now = time(NULL);
    printf("[%s][%s][%s] %s\n", ctime(&now), level_strings[level], module, text);
}
'; break; } } } void disable_module(const char* module) { for (int i = 0; i < MAX_MODULES; i++) { if (strcmp(enabled_modules[i], module) == 0) { enabled_modules[i][0] = '
#include "logger.h"
#include <stdio.h>
#include <stdlib.h>

static FILE* log_file = NULL;

void init_logging(const char* filename) {
    if (filename) {
        log_file = fopen(filename, "a");
        if (!log_file) {
            fprintf(stderr, "Failed to open log file: %s\n", filename);
            exit(EXIT_FAILURE);
        }
    } else {
        log_file = stdout; // Default to standard output
    }
}

void close_logging() {
    if (log_file && log_file != stdout) {
        fclose(log_file);
        log_file = NULL;
    }
}

void log_message(const char* text) {
    if (!log_file) {
        fprintf(stderr, "Logging not initialized.\n");
        return;
    }
    time_t now = time(NULL);
    fprintf(log_file, "[%s] %s\n", ctime(&now), text);
    fflush(log_file); // Ensure the message is written immediately
}
'; break; } } } static int is_module_enabled(const char* module) { for (int i = 0; i < MAX_MODULES; i++) { if (strcmp(enabled_modules[i], module) == 0) { return 1; } } return 0; } void log_message(const char* module, const char* text) { if (!is_module_enabled(module)) { return; } time_t now = time(NULL); printf("[%s][%s] %s\n", ctime(&now), module, text); }

說(shuō)明:

  • 生產(chǎn)者-消費(fèi)者模型:主線程生成日志消息并將它們添加到隊(duì)列中。日志工作線程消耗隊(duì)列中的消息并將其寫入日志文件。
  • 線程同步:互斥體和條件變量確保對(duì)共享資源的線程安全訪問(wèn)。
  • 正常關(guān)閉:logging_active 標(biāo)志和條件變量會(huì)在日志記錄關(guān)閉時(shí)通知工作線程退出。

外部參考:

  • 生產(chǎn)者-消費(fèi)者問(wèn)題
  • POSIX 線程編程

4. 擴(kuò)大測(cè)試和驗(yàn)證

測(cè)試對(duì)于確保日志系統(tǒng)在各種條件下正常運(yùn)行至關(guān)重要。

使用 Unity 測(cè)試框架:

Unity 是一個(gè)輕量級(jí)的 C 測(cè)試框架。

設(shè)置:

  1. 從官方存儲(chǔ)庫(kù)下載Unity:GitHub 上的Unity
  2. 在您的測(cè)試文件中包含 unity.h。

測(cè)試文件(test_logger.c):

#include "logger.h"

int main() {
    init_logging("application.log");

    log_message("Application started");
    log_message("Performing operation...");
    log_message("Operation completed.");

    close_logging();
    return 0;
}

編譯并運(yùn)行測(cè)試:

gcc -o app main.c logger.c
./app

說(shuō)明:

  • setUp 和tearDown: 在每次設(shè)置和清理測(cè)試之前和之后運(yùn)行的函數(shù)。
  • 斷言: 使用 TEST_ASSERT_* 宏來(lái)驗(yàn)證條件。
  • 測(cè)試用例:測(cè)試涵蓋記錄到標(biāo)準(zhǔn)輸出和文件。

外部參考:

  • 統(tǒng)一測(cè)試框架
  • C 語(yǔ)言的單元測(cè)試

5. 安全增強(qiáng)

確保日志系統(tǒng)的安全至關(guān)重要,尤其是在處理敏感數(shù)據(jù)時(shí)。

使用 TLS 安全傳輸:

要通過(guò)網(wǎng)絡(luò)安全地發(fā)送日志,請(qǐng)使用 TLS 加密。

使用 OpenSSL 實(shí)現(xiàn)(logger.c):

#ifndef LOGGER_H
#define LOGGER_H

#include <stdio.h>
#include <time.h>

// Function prototypes
void log_message(const char* text);

#endif // LOGGER_H

外部參考:

  • OpenSSL 文檔
  • 使用 OpenSSL 進(jìn)行安全編程

遵守?cái)?shù)據(jù)保護(hù)法規(guī):

記錄個(gè)人數(shù)據(jù)時(shí),確保遵守 GDPR 等法規(guī)。

推薦:

  • 匿名化:刪除或掩蓋日志中的個(gè)人標(biāo)識(shí)符。
  • 訪問(wèn)控制:限制對(duì)日志文件的訪問(wèn)。
  • 數(shù)據(jù)保留策略:定義日志的存儲(chǔ)時(shí)間。

外部參考:

  • 歐盟 GDPR 合規(guī)性
  • HIPAA 安全規(guī)則

6.利用現(xiàn)有的日志庫(kù)

有時(shí),使用完善的日志庫(kù)可以節(jié)省時(shí)間并提供額外的功能。

zlog簡(jiǎn)介:

zlog 是一個(gè)可靠、線程安全且高度可配置的 C 日志庫(kù)。

特點(diǎn):

  • 通過(guò)文件進(jìn)行配置。
  • 支持多種日志類別和級(jí)別。
  • 異步日志記錄功能。

使用示例:

  1. 安裝:
#include "logger.h"

void log_message(const char* text) {
    if (!text) {
        fprintf(stderr, "Invalid log message\n");
        return;
    }
    time_t now = time(NULL);
    printf("[%s] %s\n", ctime(&now), text);
}
  1. 配置文件(zlog.conf):
#include "logger.h"

int main() {
    log_message("Application started");
    log_message("Performing operation...");
    log_message("Operation completed.");
    return 0;
}
  1. 實(shí)現(xiàn)(main.c):
gcc -o app main.c logger.c
./app
  1. 編譯并運(yùn)行:
[Mon Sep 27 14:00:00 2021
] Application started
[Mon Sep 27 14:00:00 2021
] Performing operation...
[Mon Sep 27 14:00:00 2021
] Operation completed.

外部參考:

  • zlog官方網(wǎng)站
  • log4c 項(xiàng)目

與自定義實(shí)現(xiàn)的比較:

  • 使用圖書館的優(yōu)點(diǎn):

    • 節(jié)省開發(fā)時(shí)間。
    • 提供高級(jí)功能。
    • 經(jīng)過(guò)充分測(cè)試和維護(hù)。
  • 缺點(diǎn):

    • 可能包含不必要的功能。
    • 添加外部依賴項(xiàng)。
    • 對(duì)內(nèi)部運(yùn)作的控制較少。

7. 加強(qiáng)結(jié)論

最后,讓我們強(qiáng)化關(guān)鍵要點(diǎn)并鼓勵(lì)進(jìn)一步探索。

最后的想法:

構(gòu)建強(qiáng)大的日志系統(tǒng)是軟件開發(fā)的一個(gè)關(guān)鍵方面。通過(guò)關(guān)注代碼一致性、錯(cuò)誤處理、清晰度、測(cè)試、安全性并在適當(dāng)?shù)臅r(shí)候利用現(xiàn)有工具,您可以為增強(qiáng)應(yīng)用程序的可維護(hù)性和可靠性奠定基礎(chǔ)。

號(hào)召性用語(yǔ):

  • 應(yīng)用概念:將這些增強(qiáng)功能集成到您的項(xiàng)目中。
  • 進(jìn)一步探索: 研究更高級(jí)的日志記錄功能,例如日志輪換、過(guò)濾和分析工具。
  • 保持更新:及時(shí)了解日志記錄和軟件開發(fā)方面的最佳實(shí)踐和新興技術(shù)。

其他資源:

  • 日志記錄的藝術(shù)

以上是用 C 創(chuàng)建健壯的日志系統(tǒng)的詳細(xì)內(nèi)容。更多信息請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)代碼編輯軟件(SublimeText3)

在C中使用std :: Chrono 在C中使用std :: Chrono Jul 15, 2025 am 01:30 AM

std::chrono在C 中用于處理時(shí)間,包括獲取當(dāng)前時(shí)間、測(cè)量執(zhí)行時(shí)間、操作時(shí)間點(diǎn)與持續(xù)時(shí)間及格式化解析時(shí)間。1.獲取當(dāng)前時(shí)間使用std::chrono::system_clock::now(),可轉(zhuǎn)換為可讀字符串但系統(tǒng)時(shí)鐘可能不單調(diào);2.測(cè)量執(zhí)行時(shí)間應(yīng)使用std::chrono::steady_clock以確保單調(diào)性,并通過(guò)duration_cast轉(zhuǎn)換為毫秒、秒等單位;3.時(shí)間點(diǎn)(time_point)和持續(xù)時(shí)間(duration)可相互操作,但需注意單位兼容性和時(shí)鐘紀(jì)元(epoch)

C中的揮發(fā)性關(guān)鍵字是什么? C中的揮發(fā)性關(guān)鍵字是什么? Jul 04, 2025 am 01:09 AM

volatile告訴編譯器變量的值可能隨時(shí)改變,防止編譯器優(yōu)化訪問(wèn)。1.用于硬件寄存器、信號(hào)處理程序或線程間共享變量(但現(xiàn)代C 推薦std::atomic)。2.每次訪問(wèn)都直接讀寫內(nèi)存而非緩存到寄存器。3.不提供原子性或線程安全,僅確保編譯器不優(yōu)化讀寫。4.與const相反,有時(shí)兩者結(jié)合使用表示只讀但可外部修改的變量。5.不能替代互斥鎖或原子操作,過(guò)度使用會(huì)影響性能。

如何在C中獲得堆棧跟蹤? 如何在C中獲得堆棧跟蹤? Jul 07, 2025 am 01:41 AM

在C 中獲取堆棧跟蹤的方法主要有以下幾種:1.在Linux平臺(tái)使用backtrace和backtrace_symbols函數(shù),通過(guò)包含獲取調(diào)用棧并打印符號(hào)信息,需編譯時(shí)添加-rdynamic參數(shù);2.在Windows平臺(tái)使用CaptureStackBackTrace函數(shù),需鏈接DbgHelp.lib并依賴PDB文件解析函數(shù)名;3.使用第三方庫(kù)如GoogleBreakpad或Boost.Stacktrace,可跨平臺(tái)并簡(jiǎn)化堆棧捕獲操作;4.在異常處理中結(jié)合上述方法,在catch塊中自動(dòng)輸出堆棧信

什么是C中的POD(普通舊數(shù)據(jù))類型? 什么是C中的POD(普通舊數(shù)據(jù))類型? Jul 12, 2025 am 02:15 AM

在C 中,POD(PlainOldData)類型是指結(jié)構(gòu)簡(jiǎn)單且與C語(yǔ)言數(shù)據(jù)處理兼容的類型。它需滿足兩個(gè)條件:具有平凡的拷貝語(yǔ)義,可用memcpy復(fù)制;具有標(biāo)準(zhǔn)布局,內(nèi)存結(jié)構(gòu)可預(yù)測(cè)。具體要求包括:所有非靜態(tài)成員為公有、無(wú)用戶定義構(gòu)造函數(shù)或析構(gòu)函數(shù)、無(wú)虛函數(shù)或基類、所有非靜態(tài)成員自身為POD。例如structPoint{intx;inty;}是POD。其用途包括二進(jìn)制I/O、C互操作性、性能優(yōu)化等??赏ㄟ^(guò)std::is_pod檢查類型是否為POD,但C 11后更推薦用std::is_trivia

如何從c打電話給python? 如何從c打電話給python? Jul 08, 2025 am 12:40 AM

要在C 中調(diào)用Python代碼,首先要初始化解釋器,然后可通過(guò)執(zhí)行字符串、文件或調(diào)用具體函數(shù)實(shí)現(xiàn)交互。1.使用Py_Initialize()初始化解釋器并用Py_Finalize()關(guān)閉;2.用PyRun_SimpleString執(zhí)行字符串代碼或PyRun_SimpleFile執(zhí)行腳本文件;3.通過(guò)PyImport_ImportModule導(dǎo)入模塊,PyObject_GetAttrString獲取函數(shù),Py_BuildValue構(gòu)造參數(shù),PyObject_CallObject調(diào)用函數(shù)并處理返回

C中隱藏了什么功能? C中隱藏了什么功能? Jul 05, 2025 am 01:44 AM

functionHidingInc發(fā)生了swhenAderivedClassDefinesAfunctionWithThesamenAmeAsabaseClassFunction,MakeTheBaseVersionInAccessiblethroughthredtheDerivedClass.thishishappenswhishenphenthenthenthebasefunctionisfunctionis notvirtulorsignaturesignaturesignaturesignaturesignaturesignaturesnotmatchforoverRoverriding,and andNousingDeclateClateDeclaratiantiesdeclaratianisingdeclaratrationis

C中的無(wú)效指針是什么? C中的無(wú)效指針是什么? Jul 09, 2025 am 02:38 AM

AnullpointerinC isaspecialvalueindicatingthatapointerdoesnotpointtoanyvalidmemorylocation,anditisusedtosafelymanageandcheckpointersbeforedereferencing.1.BeforeC 11,0orNULLwasused,butnownullptrispreferredforclarityandtypesafety.2.Usingnullpointershe

如何將函數(shù)作為C中的參數(shù)傳遞? 如何將函數(shù)作為C中的參數(shù)傳遞? Jul 12, 2025 am 01:34 AM

在C 中,將函數(shù)作為參數(shù)傳遞主要有三種方式:使用函數(shù)指針、std::function和Lambda表達(dá)式、以及模板泛型方式。1.函數(shù)指針是最基礎(chǔ)的方式,適用于簡(jiǎn)單場(chǎng)景或與C接口兼容的情況,但可讀性較差;2.std::function結(jié)合Lambda表達(dá)式是現(xiàn)代C 推薦的方式,支持多種可調(diào)用對(duì)象且類型安全;3.模板泛型方式最為靈活,適用于庫(kù)代碼或通用邏輯,但可能增加編譯時(shí)間和代碼體積。捕獲上下文的Lambda必須通過(guò)std::function或模板傳遞,不能直接轉(zhuǎn)換為函數(shù)指針。

See all articles