为什么当我将“beginning”分配给 memHead* 类型的可变 currentPos 时,我总是收到分段错误?

Why do I keep getting a segmentation fault when I assign 'beginning' to variable currentPos of type memHead*?

提问人:Astrospherical 提问时间:10/21/2023 最后编辑:Astrospherical 更新时间:10/21/2023 访问量:38

问:

这里是 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,也无济于事。

c 马洛克

评论

1赞 Fe2O3 10/21/2023
} else if (currentPos->next = currentPos){看起来非常可疑......没有阅读所有的代码和评论,因为我一整天都没有......评论应该说“为什么”而不是“什么”......变量名称本身需要是整个章节......简洁是智慧的灵魂......
0赞 Fe2O3 10/21/2023
引用:“什么”评论的麻烦......是代码错了,还是注释错了?newMemoryLocation->free_m = 0; //sets the free_m variable to 1 to...
0赞 Barmar 10/21/2023
你能添加一下,这样我们就可以尝试自己编译这个吗?myfree
0赞 Astrospherical 10/21/2023
我添加了myfree。我还修复了评论,评论肯定是错误的。我也会减少评论。
0赞 Barmar 10/21/2023
我补充了一些语句。崩溃发生在 ,而不是 。printfmyfree()mymalloc()

答: 暂无答案