私は、CS107 - Programming Paradigms(Stanfordのオンラインコース)の講義5と6に示されているジェネリックスタックを実装しようとしています。 講義で提示された例を表す次のコードはコンパイルされますが、しばしばアサーションエラーが発生するため、一貫して動作しないようです。なぜこのコードは一貫して動作しませんか?
は、私はGeanyとGCC($ gcc --version gcc (Debian 6.3.0-18) 6.3.0 20170516
)での行動に気づいてきましたが、ないhttps://www.tutorialspoint.com/compile_c_online.php `に"ので、私はそれがGCCで何かまたは私が今見ていないようだバグによって引き起こされている場合だろうか。
コード:
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include <assert.h>
typedef struct {
void *elems;
int elemSize;
int logLen;
int allocLen;
} stack;
void StackNew(stack *s, int elemSize);
void StackDispose(stack *s);
void StackPush(stack *s, void *elemAddr);
void StackPop(stack *s, void * elemAddr);
void StackNew(stack *s, int elemSize)
{
assert(s->elemSize > 0);
s->elemSize = elemSize;
s->logLen = 0;
s->allocLen = 4;
s->elems = malloc(4 * elemSize);
assert(s->elems != NULL);
}
void StackDispose(stack *s)
{
free(s->elems);
}
static void StackGrow(stack *s)
{
s->allocLen *= 2;
s->elems = realloc(s->elems, s->allocLen * s->elemSize);
}
void StackPush(stack *s, void *elemAddr)
{
if(s->logLen == s->allocLen)
StackGrow(s);
void *target = (char *) s->elems + s->logLen * s->elemSize;
memcpy(target, elemAddr, s->elemSize);
s->logLen++;
}
void StackPop(stack *s, void *elemAddr)
{
void *source = (char *) s->elems +
(s->logLen - 1) * s->elemSize;
memcpy(elemAddr, source, s->elemSize);
s->logLen--;
}
int main(void)
{
const char *friends[] = {"Al", "Bob", "Carl"};
stack stringStack;
StackNew(&stringStack, sizeof(char *));
int i;
for (i = 0; i < 3; i++){
char *copy = strdup(friends[i]);
StackPush(&stringStack, ©);
}
char *name;
for (i = 0; i < 3; i++) {
StackPop(&stringStack, &name);
printf("%s\n", name);
free(name);
}
StackDispose(&stringStack);
return 0;
}
任意のソースの修正なしに、いくつかの連続実行のための出力例:あなたはそれを設定する前s->elemSize
をチェックしている
$ ./stack4
stack4: stack4.c:21: StackNew: Assertion 's->elemSize' > 0 failed.
Aborted
$ ./stack4
stack4: stack4.c:21: StackNew: Assertion 's->elemSize' > 0' failed.
Aborted
$ ./stack4
Carl
Bob
Al
$ ./stack4
Carl
Bob
Al
$ ./stack4
Carl
Bob
Al
$ ./stack4
stack4: stack4.c:21: StackNew: Assertion 's->elemSize' > 0' failed.
Aborted
$ ./stack4
stack4: stack4.c:21: StackNew: Assertion 's->elemSize' > 0 failed.
Aborted
$ ./stack4
Carl
Bob
Al
$ ./stack4
stack4: stack4.c:21: StackNew: Assertion 's->elemSize' > 0' failed.
私は 'StackNew(&stringStack、sizeof(char **));'は正しいとは思わない。 'sizeof(char **)'は要素のサイズでなければなりません。このコードの場合は 'char *'です。通常、これらの異なるポインタ型は同じサイズを持っています – chux
堅牢な_generic stack_は、サイズの計算に 'int'、' elemSize'ではなく 'size_t'を使用します。 – chux
'sizeof(char *)'は私の側では間違いですが、私は質問でそれを修正しました(コードを少し演奏して質問を投稿したときにそれを見逃していました)。より一般的な実装のために 'size_t'に言及していただきありがとうございます。講義は整数のスタックから始まりました。そして、そのバージョンはますます汎用的になるように徐々に修正されていきました。最終的には頑強な実装に変わります。 – 0ana