尝试更改内存地址处的值时出现分段错误

Segmentation Fault When Trying to Change Values at Memory Address

我发现了一个 seg fault 错误,它出现在我的 divideBlock() 函数中。当我取消引用 newBlock 以访问信息时,即没有为其分配值而只是取消引用它,这没问题,但是当我更改它的值时,我收到了一个设置错误。知道为什么会这样吗?可能是因为地址操作和非标准指针访问吗?如果是这样,我想把一个块一分为二怎么办?

typedef struct freeBlock
{
    size_t info;
    struct freeBlock *next;
} freeBlock;

freeBlock *divideBlock(freeBlock *block, size_t reqSize)
{
    // Declaration of variables.
    freeBlock *newBlock;
    size_t blockSize;

    blockSize = block->info >> 1;
    newBlock = block + reqSize;

    newBlock->info = (blockSize - reqSize) << 1; // new block marked as unused. seg fault happens here!!!
    block->info = (reqSize << 1) | 1; // old block marked as used.

    return newBlock;
}

void *malloc(size_t size)
{
    if (size == 0)
        return NULL;
    // Declaration of variables. 
    size_t blockSize, occpd, poccpd, reqSize;
    freeBlock *curr, *prev, *newBlock, *allocd, *combined;

    printf("%d", __LINE__);
    reqSize = (size + sizeof(size_t) + sizeof(char*) + padding + (align - 1)) & ~ (align - 1);

    printf("%d", __LINE__);
    curr = head;
    prev = NULL;
    while (curr != NULL)
    {
    printf("%d", __LINE__);
        occpd = curr->info & 1;

        if (prev != NULL)
        {
    printf("%d", __LINE__);
            poccpd = prev->info & 1;
            if (!poccpd && !occpd)
            {
                 combined = combineBlock(prev, curr);
                if (combined)
                    curr = combined;
            }
        }

        blockSize  = curr->info >> 1;

    printf("%d", __LINE__);
        if (blockSize >= reqSize && !occpd)
        {
            if (blockSize >= 2 * reqSize)
            {
                newBlock = divideBlock(curr, reqSize);
                if (newBlock != NULL)
                {
                    newBlock->next = curr->next;
                    curr->next = newBlock;
                }
            }
            curr->info |= 1;
            return curr + sizeof(char*) + sizeof(size_t);
        }
        prev = curr;
        curr = curr->next;
    }

    printf("%d", __LINE__);

    allocd = sbrk(reqSize * 3);
    if (allocd == (void*)-1)
        return NULL;

    allocd->info = ((reqSize * 3) << 1) | 1;
    newBlock = divideBlock(allocd, reqSize);
    newBlock->next = NULL;
    allocd->next = newBlock;

    if (head == NULL)
        head = allocd;
    else
        curr = allocd;

    return allocd + sizeof(char *) + sizeof(size_t);
}

问题好像出在这行:

newBlock = block + reqSize;

newBlock 将指向 "location-of-block + reqSize*sizeof(freeBlock)"

的位置(地址)

可能的意图只是让 newBlock 指向块后 reqSize 字节的位置。

要将指针递增 1,您可以在添加 reqSize 之前将其转换为 char*。

也许像这样的划分:

freeBlock *divideBlock(freeBlock *block, size_t reqSize)
{
    // Declaration of variables.
    freeBlock *newBlock;
    size_t blockSize;

    blockSize = block->info >> 1;
    newBlock = (freeBlock*)(((char*)block) + reqSize);

    newBlock->info = (blockSize - reqSize) << 1;
    block->info = (reqSize << 1) | 1; // old block marked as used.

    return newBlock;
}

但是您在 malloc 函数中也有问题,您将数字添加到 freeBlock 类型的指针。可能不是你想要的。

顺便说一句: 为什么使用

sizeof(char *) + sizeof(size_t)

不应该是

sizeof(freeBlock)