【问题标题】:Segmentation Fault When Trying to Change Values at Memory Address [closed]尝试更改内存地址处的值时出现分段错误
【发布时间】:2015-08-10 18:16:17
【问题描述】:

我发现了一个段错误错误,它发生在我的 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);
}

【问题讨论】:

  • freeBlock *block的内存是怎么分配的?
  • 我使用了 sbrk()。这应该是 malloc() 实现的一部分,如果它太大,它应该将一个空闲内存主干分成两部分。
  • 你的问题我还不清楚,但block + reqSize 可能不会像你想的那样做。
  • 看起来像 未定义的行为。请阅读 C 中的指针算法。请提供minimal reproducible example
  • @skydiving94 “然后我添加 32 个字节” - 不,你没有。您添加 32 个freeBlocks。

标签: c segmentation-fault malloc


【解决方案1】:

问题似乎出在这条线上:

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)

【讨论】:

  • 是的,这很愚蠢,哈哈。我会把它修好!而且我还按照您向我展示的方式进行了指示。它有效!
猜你喜欢
  • 2016-05-08
  • 2022-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
  • 2015-08-27
相关资源
最近更新 更多