簡體   English   中英

C編程,char數組內存分配問題

[英]C programming, char array memory allocation issue

我正在開發一個小的C庫來教視頻游戲編程,並且我創建了一個簡單的函數來在屏幕上繪制格式化的文本(即得分,生命)。 該函數是:

const char *FormatText(const char *text, ...)
{
    int length = strlen(text);
    char *buffer = malloc(length + 20);

    va_list args;
    va_start(args, text);
    vsprintf(buffer, text, args);
    va_end(args);

    return buffer;
}

此功能在游戲主循環的“繪制”部分中使用,如下所示:

DrawText(FormatText("%02i", score), 10, 10, 40, BLACK);

DrawText()函數中的其他參數僅表示屏幕坐標X,Y,字體大小和顏色。

我每秒調用此函數約60次(甚至更多),因此,如果我是對的,我將在每次調用時分配新的內存...而且我永遠不會釋放該內存!

如何解決此問題以繼續使用我的函數?

我的第一個想法是在我的庫上創建一個全局char * buffer,在初始化時分配它,然后一直重復使用...但是我不確定這是否是最好的主意,我嘗試避免使用過多的globals。

非常感謝您的回答!

UPDATE

再次感謝大家的回答。

最后,我解決此問題的方法是使用:

const char *FormatText(const char *text, ...)
{
    static char buffer[MAX_FORMATTEXT_LENGTH];

    va_list args;
    va_start(args, text);
    vsprintf(buffer, text, args);
    va_end(args);

    return buffer;
}

可能不是最好的解決方案,但我認為這對於lib用戶是最好的,而不必擔心內存管理。

這是一個簡單的用法示例:

#include "raylib.h"

int main()
{
    int score = 100020;
    int hiscore = 200450;
    int lives = 5;

    InitWindow(800, 450, "testing FormatText()");

    SetTargetFPS(60);

    while (!WindowShouldClose())    // Detect window close button or ESC key
    {
        BeginDrawing();

            ClearBackground(RAYWHITE);

            DrawText(FormatText("Score: %08i", score), 80, 80, 20, RED);
            DrawText(FormatText("HiScore: %08i", hiscore), 80, 120, 20, GREEN);
            DrawText(FormatText("Lives: %02i", lives), 80, 160, 40, BLUE);
            DrawText(FormatText("Elapsed Time: %02.02f ms", GetFrameTime()*1000), 80, 220, 20, BLACK);

        EndDrawing();
    }

    CloseWindow();

    return 0;
}

結果是:

測試FormatText()raylib函數

我將管理內存的責任交給了父函數。 它會根據需要分配和釋放,而不是FormatText()本身

// somefunction
    char *buffer;
    buffer = malloc(<somesize>);
    if (buffer) {
        FormatText(buffer, "%02i", ...);
        free(buffer);
    }

您的函數幾乎已經存在於某些Libc中,例如GNU libc ,它稱為asprintf(3) 調用者應free malloc分配的緩沖區。

您可以將其用作:

char* msg=NULL;
DrawText((msg=FormatText("%02i", score)), 10, 10, 40, BLACK);
free (msg);

或者,如果使用asprintf ,則使用逗號運算符

char* msg=NULL;
DrawText((asprintf(&msg,"%02i",score),msg), 10, 10, 40, BLACK);
free (msg);

最后,如果您因應該free調用而煩惱,則可以決定整個程序都使用Boehm垃圾收集器 (因此,您將調用GC_MALLOC而不用擔心GC_FREE )。 然后,您將定義

char* GC_sprintf(const char*fmt, ...) {
   char buf[128];
   va_list ap;
   va_start (ap, fmt);
   int sz = vsnprintf(buf, sizeof(buf), fmt, ap);
   va_end (ap);
   if (sz < sizeof(buf)) return GC_strdup (buf);
   char* gcbuf = GC_MALLOC_ATOMIC (sz+1);
   memset (gcbuf, 0, sizeof (gcbuf));
   va_start (ap, fmt);
   vsnprintf(gcbuf, sz, fmt, ap);
   va_end (ap);
   return gcbuf;
}

然后簡單地打電話

DrawText(GC_sprintf("%02i",score), 10, 10, 40, BLACK);

順便說一句,由於"%02i"格式會產生一個短字符串,因此您可以使用

char locbuf[8];
snprintf (locbuf, sizeof(locbuf), "%02i", score);
DrawText(locbuf, 10, 10, 40, BLACK);

您甚至可以考慮定義可變參數的DrawText_printf並調用

DrawText_printf(10, 10, 40, BLACK, "%02i", score);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM