2017-08-02 13 views
2

私は、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, &copy); 
    } 

    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. 
+0

私は 'StackNew(&stringStack、sizeof(char **));'は正しいとは思わない。 'sizeof(char **)'は要素のサイズでなければなりません。このコードの場合は 'char *'です。通常、これらの異なるポインタ型は同じサイズを持っています – chux

+0

堅牢な_generic stack_は、サイズの計算に 'int'、' elemSize'ではなく 'size_t'を使用します。 – chux

+1

'sizeof(char *)'は私の側では間違いですが、私は質問でそれを修正しました(コードを少し演奏して質問を投稿したときにそれを見逃していました)。より一般的な実装のために 'size_t'に言及していただきありがとうございます。講義は整数のスタックから始まりました。そして、そのバージョンはますます汎用的になるように徐々に修正されていきました。最終的には頑強な実装に変わります。 – 0ana

答えて

8

。初期化されていない変数を使用しています。

修正:assert(elemSize > 0)sのメンバー、関数のパラメータを確認していない)、またはs->elemSize = elemSize割り当て後assertを行うのどちらか。

関連する問題