提问人:Astrospherical 提问时间:10/21/2023 最后编辑:Astrospherical 更新时间:10/21/2023 访问量:38
为什么当我将“beginning”分配给 memHead* 类型的可变 currentPos 时,我总是收到分段错误?
Why do I keep getting a segmentation fault when I assign 'beginning' to variable currentPos of type memHead*?
问:
这里是 mymalloc.c:
#include <stdio.h>
#include <stdlib.h>
#include "mymalloc.h"
static double memory[MAX_MEMORY]; //sets maximum memory sizeOfMem to 4096 bytes as defined in "mymalloc.h"
void *beginning = (memHead *)(memory); //initializes beginning of memory. Acts as a pointer to the beginning address of the list.
void *mymalloc(size_t size, char *file, int line) { //mymalloc function
printf("mymalloc called\n");
printf("Requested working bytes (reading MAX_MEMORY): %d bytes\n", MAX_MEMORY);
memHead* currentPos = beginning; //sets the current position to be the front of the array
printf("Successfully set currentPos to beginning.");
if(((currentPos)->next) == NULL){ //Checks whether currentPos points to an empty list
double requestMemForHead = MAX_MEMORY-size; //calculates the amount of memory requested
if(size<requestMemForHead){ //Is the memory requested less than the memory available?
(currentPos)->free_m = 0; //sets the free_m variable to 0 to indicate that the memory is no longer free (if it is available to allocate)
void* currentMemDress = currentPos; //sets the current memory address to the current position of the list
//checks whether allocation can proceed based on current allocation and request
double requestMemLeftForAlloc = MAX_MEMORY-sizeOfMemHead;
if(requestMemLeftForAlloc>sizeOfMemHead){
struct memHead* newMemoryLocation = (memHead*) currentMemDress + (int) sizeOfMemHead + size; //tracks memory address and metadata
newMemoryLocation->sizeOfMem = MAX_MEMORY - 2*sizeOfMemHead - size; //sets sizeOfMem to hold requested amount plus some
newMemoryLocation->free_m = 0; //sets the free_m variable to 0 to indicate that the memory is not free
newMemoryLocation->next = currentPos; //sets the next pointer to original position (beginning of array)
currentPos->next = newMemoryLocation; //sets the next pointer of the previous location to the new memory location
currentPos->sizeOfMem = size; //sets the sizeOfMem of the current position to the size requested
} else {
currentPos->next = currentPos;
currentPos->sizeOfMem = MAX_MEMORY-sizeOfMemHead;
}
return(currentPos+1); //returns the address of the allocated memory
}
else {
printf("Error: Not enough memory available to allocate. Here's where it failed: File %s: Line %d: \n", file, line); //if there is not enough memory available, throw error.
return NULL;
}
}
if ((currentPos) != NULL){ //if malloc was already run, skip initialization and iterate through the array to find an empty chunk
while ((currentPos) != NULL) {
if (((currentPos)->free_m) && ((currentPos)->sizeOfMem) >= size) {
return currentPos;
} else if (currentPos->next = currentPos){
printf("Error: Not enough memory available to allocate. There are no free chunks available.\n");
return NULL;
}
currentPos = currentPos->next; //found a node, set currentPos to it
currentPos->free_m = 0; //once found, set the free_m variable to 0 to indicate that the memory is no longer free (if it is available to allocate)
}
}
if((((currentPos)->sizeOfMem) - size) > sizeOfMemHead) {
char* currentMemDress = (char*)currentPos;
struct memHead* naeMemoryLocation = (memHead*) currentMemDress + sizeOfMemHead + size;
naeMemoryLocation->sizeOfMem = currentPos->sizeOfMem - sizeOfMemHead - size;
naeMemoryLocation->free_m = 0;
naeMemoryLocation->next = currentPos->next;
currentPos->next = naeMemoryLocation;
currentPos->sizeOfMem = size;
}
void* dataAddress = (currentPos+1);
void* headerAddress = currentPos;
printf("Data address: %p\n", dataAddress);
printf("Header address: %p\n", headerAddress);
return(dataAddress);
}
void myfree(void *pnt, char *file, int line){
if (!pnt) {
if(pnt >= beginning + MAX_MEMORY){
printf("Error: Cannot free memory that is not within the confines of the array. Here's where it failed: Your pointer: %p\n File: %s\n Line: %d\n", pnt, file, line);
return;
} else {
printf("Error: Cannot free a null pointer. Here's where it failed: Your pointer: %p\n File: %s\n Line: %d\n", pnt, file, line);
return;
}
}
memHead* preBAddress = (memHead*)pnt-sizeOfMemHead;
if(preBAddress->free_m == 1){
printf("Error: Cannot free memory. Either invalid pointer or it was already freed. Here's where it failed: Your pointer: %p\n File: %s\n Line: %d\n", pnt, file, line);
return;
} else if((preBAddress)->free_m = 0){
preBAddress->free_m = 1;
printf("Memory freed successfully.\n");
return;
}
//we're coalescing two blocks. (left -> right)
memHead* postBAddress = preBAddress->next;
if(postBAddress->free_m == 1){
printf("Found an available free block. Checking where it's located.\n");
if(postBAddress == beginning){
printf("This wasn't supposed to happen. Either you haven't run malloc yet or this array isn't correct.\n"); //something got borked.
return;
} else if(postBAddress != beginning) {
printf("Found blocks at address %p and address %p...\n", preBAddress, postBAddress);
preBAddress->sizeOfMem = preBAddress->sizeOfMem + sizeOfMemHead + postBAddress->sizeOfMem; // adds the size of the metadata and the size of the block to the sizeOfMem of the preBAddress block, effectively combining the two blocks.
preBAddress->next = postBAddress->next; //sets the next pointer of the new block to the location after the original postBAddress block.
postBAddress = NULL; //nulls the block as it technically is part of preBAddress now.
printf("Blocks coalesced successfully. Block address is %p.\n", preBAddress); //specifies the block addresses
return;
}
}
// now we check whether there are blocks to the left that are free and can be coalesced. (right -> left)
memHead* currentPos = beginning;
while(currentPos != NULL && !(currentPos->next == preBAddress && currentPos->free_m == 1 && currentPos != beginning)) {
if (currentPos->next == beginning) { //checks whether the next block is the beginning of the array
printf("We're at the last bit. Whoops.");
return;
}
currentPos = currentPos->next; //sets the current position to the next block
}
printf("Found a free block to the left of the block you're trying to free. Coalescing blocks...\n");
currentPos->sizeOfMem = currentPos->sizeOfMem + sizeOfMemHead + preBAddress->sizeOfMem; // adds the size of the metadata and the size of the block to the sizeOfMem of the preBAddress block, effectively combining the two blocks.
currentPos->next = preBAddress->next; //sets the next pointer of the new block to the location after the original postBAddress block.
preBAddress = NULL; //nulls the block as it technically is part of preBAddress now.
printf("Blocks coalesced successfully. Block address is %p.\n", currentPos); //specifies the block addresses
};
这是我的头文件:
#ifndef MALLOC_H
#define MALLOC_H
#include <stddef.h>
void *mymalloc(size_t size, char *file, int line);
void myfree(void *pnt, char *file, int line);
#define MAX_MEMORY 4096
typedef struct memHead {
int sizeOfMem;
int free_m;
struct memHead* next;
}memHead;
#define malloc(s) mymalloc(s, __FILE__, __LINE__)
#define free(p) myfree(p, __FILE__, __LINE__)
#define sizeOfMemHead sizeof(struct memHead)
#endif
例如,我尝试像这样使用 malloc:
for(int i=0;i<120;i++){
char *p = malloc(1);
free(p);
}
我的输出是:
mymalloc called
Requested working bytes (reading MAX_MEMORY): 4096 bytes
Segmentation fault
它无法将指针分配给数组的开头。我做错了什么吗?我已经将 printf 语句设置为 memHead* currentPos 之后的点,该点旨在分配 beginning 值,但它从未到达该点,因此我确信问题出在 .memHead* currentPos = beginning;
我试图将内存数组的类型更改为 char,也无济于事。
答: 暂无答案
评论
} else if (currentPos->next = currentPos){
看起来非常可疑......没有阅读所有的代码和评论,因为我一整天都没有......评论应该说“为什么”而不是“什么”......变量名称本身需要是整个章节......简洁是智慧的灵魂......newMemoryLocation->free_m = 0; //sets the free_m variable to 1 to...
myfree
printf
myfree()
mymalloc()