1

今、私はCインターフェースと実装を読んでいます.4番目の図表はメモリ管理です.Mem_alloc関数によって返されるブロックに任意のタイプのデータを格納できることをアラインメントが保証すると言いました.この文をどのように理解できますか?メモリを管理するときに整列しますか?

整列コードは次のとおりです。

union align {
#ifdef MAXALIGN
        char pad[MAXALIGN];
#else
        int i;
        long l;
        long *lp;
        void *p;
        void (*fp)(void);
        float f;
        double d;
        long double ld;
#endif
void *Mem_alloc(long nbytes, const char *file, int line){
        struct descriptor *bp;
        void *ptr;
        assert(nbytes > 0);
        nbytes = ((nbytes + sizeof (union align) - 1)/
                (sizeof (union align)))*(sizeof (union align));
        for (bp = freelist.free; bp; bp = bp->free) {
                if (bp->size > nbytes) {
                        bp->size -= nbytes;
                        ptr = (char *)bp->ptr + bp->size;
                        if ((bp = dalloc(ptr, nbytes, file, line)) != NULL) {
                                unsigned h = hash(ptr, htab);
                                bp->link = htab[h];
                                htab[h] = bp;
                                return ptr;
                        } else
                                {
                                        if (file == NULL)
                                                RAISE(Mem_Failed);
                                        else
                                                Except_raise(&Mem_Failed, file, line);
                                }
                }
                if (bp == &freelist) {
                        struct descriptor *newptr;
                        if ((ptr = malloc(nbytes + NALLOC)) == NULL
                        ||  (newptr = dalloc(ptr, nbytes + NALLOC,
                                        __FILE__, __LINE__)) == NULL)
                                {
                                        if (file == NULL)
                                                RAISE(Mem_Failed);
                                        else
                                                Except_raise(&Mem_Failed, file, line);
                                }
                        newptr->free = freelist.free;
                        freelist.free = newptr;
                }
        }
        assert(0);
        return NULL;
}
    };

 void *Mem_resize(void *ptr, long nbytes,
        const char *file, int line) {
        struct descriptor *bp;
        void *newptr;
        assert(ptr);
        assert(nbytes > 0);
        if (((unsigned long)ptr)%(sizeof (union align)) != 0
        || (bp = find(ptr)) == NULL || bp->free)
                Except_raise(&Assert_Failed, file, line);
        newptr = Mem_alloc(nbytes, file, line);
        memcpy(newptr, ptr,
                nbytes < bp->size ? nbytes : bp->size);
        Mem_free(ptr, file, line);
        return newptr;
}  

これらのコードを理解するにはどうすればよいですか?スペースのサイズを変更するときに if (((unsigned long)ptr)%(sizeof (union align)) != 0 にする必要があるのはなぜですか?

4

1 に答える 1

1

CPU には、データの処理に制限があります。たとえば、ポインタは一般に、32 ビット CPU では 4 バイト アライン、64 ビット CPU では 8 バイト アラインである必要があります。さらに、アラインされていない境界でのデータのロードと格納が許可されている場合でも、パフォーマンスが低下する可能性があります。たとえば、CPU は奇数アドレスからロードできるかもしれませんが、2 倍のサイクルが必要になります。これは多くの場合、メモリ ハードウェアが 4、8、または 16 バイト境界でデータを取得するように最適化されており、データ ワードの下位部分を 1 サイクルでロードしてから、次のサイクルで上位部分をロードする必要があるためです。

そのため、コンパイラを実装するときは、これらのアラインメントが必要な CPU で適切に動作する必要があります。

Intel の IA-64 アライメント要件の例については、こちらを参照してください。

  • 任意のアドレスで 8 ビット データを整列
  • アライメントされた 4 バイト ワード内に含まれる 16 ビット データをアライメントします。
  • ベース アドレスが 4 の倍数になるように 32 ビット データを整列します。
  • ベース アドレスが 8 の倍数になるように 64 ビット データを整列する
  • ベース アドレスが 16 の倍数になるように 80 ビット データを整列する
  • ベース アドレスが 16 の倍数になるように 128 ビット データを整列する
于 2013-10-15T03:17:42.927 に答える