GST システムをシミュレートするのに十分な擬似インフラストラクチャを追加してコンパイル可能なコードに変換すると、GCC は、ほぼ確実に問題の原因である警告を表示します。
gstq.c: In function ‘dequeue_gstbuffer’:
gstq.c:73:12: warning: ‘nextPtr’ is used uninitialized in this function [-Wuninitialized]
行は次のとおりです。
72 GstBufferQueue **nextPtr;
73 *nextPtr = (*head)->next;
これらの行では、次のものが必要です。
GstBufferQueue *nextPtr = (*head)->next;
以下も使用する必要があります。
(*head)->next = nextPtr;
コンパイラの警告に注意してください。コンパイラが警告しない場合は、警告するようにします。警告を表示できない場合は、より優れたコンパイラを入手してください。
SSCCE
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#define GST_BUFFER_SIZE(x) sizeof(x)
#define GST_WARNING(x) fprintf(stderr, "%s\n", x)
typedef struct GstBuffer { int value; } GstBuffer;
typedef unsigned int guint;
static GstBuffer *gst_buffer_try_new_and_alloc(int size)
{
GstBuffer *buf = malloc(sizeof(GstBuffer));
assert(buf != 0);
buf->value = size;
return buf;
}
static GstBuffer *gst_buffer_copy(const GstBuffer *buf)
{
GstBuffer *new_buf = malloc(sizeof(GstBuffer));
assert(new_buf != 0);
new_buf->value = buf->value;
return new_buf;
}
static void gst_buffer_unref(GstBuffer *buf)
{
buf->value = -1;
}
typedef struct _GstBUFFERQUEUE GstBufferQueue;
struct _GstBUFFERQUEUE {
GstBuffer *buf;
guint buf_size;
struct _GstBUFFERQUEUE *next;
};
extern void enqueue_gstbuffer(GstBufferQueue **head, GstBufferQueue **tail, guint *queue_size, GstBuffer *buf);
extern void dequeue_gstbuffer(GstBufferQueue **head, GstBufferQueue **tail, guint *queue_size, GstBuffer **buf);
void enqueue_gstbuffer(GstBufferQueue **head, GstBufferQueue **tail, guint *queue_size, GstBuffer *buf)
{
if (*queue_size == 0)
{
*head = malloc(sizeof(GstBufferQueue));
(*head)->buf = gst_buffer_try_new_and_alloc(GST_BUFFER_SIZE(buf));
(*head)->buf = gst_buffer_copy(buf);
*tail = *head;
}
else
{
if (((*tail)->next = malloc(sizeof(GstBufferQueue))) != 0)
{
(*tail)->next->buf = gst_buffer_try_new_and_alloc(GST_BUFFER_SIZE(buf));
(*tail)->next->buf = gst_buffer_copy(buf);
(*tail) = (*tail)->next;
}
else
{
GST_WARNING("Error allocating memory for new buffer in queue");
}
}
(*tail)->next = NULL;
(*queue_size)++;
}
void dequeue_gstbuffer(GstBufferQueue **head, GstBufferQueue **tail, guint *queue_size, GstBuffer **buf)
{
GstBufferQueue **tmpPtr = head;
GstBufferQueue *nextPtr;
nextPtr = (*head)->next;
*buf = gst_buffer_try_new_and_alloc (GST_BUFFER_SIZE((*tmpPtr)->buf));
*buf = gst_buffer_copy((*tmpPtr)->buf);
gst_buffer_unref((*tmpPtr)->buf);
free((*tmpPtr));
*head = nextPtr;
if ((*head) == NULL)
(*tail) = NULL;
(*queue_size)--;
}
int main(void)
{
GstBufferQueue *q_head = 0;
GstBufferQueue *q_tail = 0;
guint q_size = 0;
for (int i = 0; i < 10; i++)
{
GstBuffer *buf = gst_buffer_try_new_and_alloc(i + 100);
enqueue_gstbuffer(&q_head, &q_tail, &q_size, buf);
printf("EQ: %d\n", buf->value);
free(buf);
if (i % 2 == 1)
{
GstBuffer *buf;
dequeue_gstbuffer(&q_head, &q_tail, &q_size, &buf);
printf("DQ: %d\n", buf->value);
free(buf);
}
}
while (q_size > 0)
{
GstBuffer *buf;
dequeue_gstbuffer(&q_head, &q_tail, &q_size, &buf);
printf("DQ: %d\n", buf->value);
free(buf);
}
printf("All done\n");
return(0);
}
出力
EQ: 100
EQ: 101
DQ: 100
EQ: 102
EQ: 103
DQ: 101
EQ: 104
EQ: 105
DQ: 102
EQ: 106
EQ: 107
DQ: 103
EQ: 108
EQ: 109
DQ: 104
DQ: 105
DQ: 106
DQ: 107
DQ: 108
DQ: 109
All done
上記の SSCCE コードはふるいよりも漏れが悪いことに注意してください。GST バッファー管理をシミュレートするコードにリークがあるため、リークを修正する予定はありません。コードがメモリ リークの影響を受けていないことを確認してください。
「キュー」を別の方法でパッケージ化する必要があると思います。a と呼ぶものGstBufferQueue
は実際には aGstBufferQueueItem
である必要があり、実際GstBufferQueue
にはヘッドとテールのポインター、およびサイズが含まれている必要があります。3 つの個別のパラメーターを渡す代わりに、(改訂された)GstBufferQueue
へのポインターをenqueue_gstbuffer()
anddequeue_gstbuffer()
関数に渡します。
typedef struct GstBufferQueueItem GstBufferQueueItem;
struct GstBufferQueueItem
{
GstBuffer *buf;
guint buf_size;
GstBufferQueueItem *next;
};
typedef struct GstBufferQueue GstBufferQueue;
struct GstBufferQueue
{
GstBufferQueueItem *head;
GstBufferQueueItem *tail;
guint size;
};
// Uncompiled - but to give you an idea
void dequeue_gstbuffer(GstBufferQueue *q, GstBuffer **buf)
{
GstBufferQueueItem *item = q->head;
GstBufferQueueItem *next = item->next;
*buf = gst_buffer_try_new_and_alloc(GST_BUFFER_SIZE(item->buf));
*buf = gst_buffer_copy(item->buf);
gst_buffer_unref(item->buf);
free(item);
q->head = next;
if (q->head == NULL)
q->tail = NULL;
q->size--;
}
これらの名前では、先頭のアンダースコアを避けることに注意してください。このような名前は危険です。アンダースコアと大文字を含む名前は、目的を問わず実装用に予約されています。アンダースコアと小文字を含む名前は異なる単語で予約されていますが、どちらを使用しても危険です (標準ではアンダースコアと数字についてほとんど言及されていませんが、それらでゲームをしないでください — 先頭のアンダースコアを「予約済み」として扱います)。 「システム」と書いていない限り)。
ISO/IEC 9899:2011 §7.1.3 予約済み識別子
- アンダースコアと大文字または別のアンダースコアで始まるすべての識別子は、常に予約されています。
- アンダースコアで始まるすべての識別子は、通常の名前空間とタグ名空間の両方で、ファイル スコープの識別子として使用するために常に予約されています。