尝试更改内存地址处的值时出现分段错误
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)
我发现了一个 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)