由于某种原因,我的程序有时工作正常,有时只是以段错误结束。我正在尝试创建 malloc 的实现。如果我从 5000
大小开始,然后执行 malloc(1000)
,我预计剩余内存大小为 3984
(由于以及内存条目的大小)。
当我使用 printf
输出剩余内存时,它有时会打印 3984
,有时会以段错误结束。任何帮助将不胜感激。
#include "malloc-free-impl.h"
static char memArr[5000];
static char* memArrPtr = &memArr;
static MemEntryPtr head = NULL;
void* custom_malloc(int size) {
if (head == NULL) {
head = (MemEntryPtr) memArrPtr;
head->prev = NULL;
head->next = NULL;
head->isFree = 1;
head->size = sizeof(memArr) - sizeof(head);
}
MemEntryPtr curr = head;
while (curr->isFree != 1 && curr->size > size + sizeof(struct MemEntry)) {
curr = curr->next;
}
if ((curr->size - (size)) > sizeof(struct MemEntry)) {
MemEntryPtr newMemEntry = (MemEntryPtr) (&curr + sizeof(struct MemEntry) + size);
newMemEntry->prev = curr;
newMemEntry->next = NULL;
newMemEntry->isFree = 1;
newMemEntry->size = curr->size - (size + sizeof(newMemEntry));
printf("%d\n", newMemEntry->size);
curr->isFree = 0;
curr->next = newMemEntry;
return newMemEntry;
}
return NULL;
}
void* custom_free(MemEntryPtr memBlock) {
memBlock->isFree = 1;
return NULL;
}
int main(int argc, char** argv) {
MemEntryPtr node = (MemEntryPtr) custom_malloc(1000);
return 1;
}
最佳答案
malloc-free-impl.h(复制问题的最小 stub )
#ifndef _malloc_free_impl_
#define _malloc_free_impl_
struct MemEntry
{
struct MemEntry *prev, *next;
int isFree, size;
};
typedef struct MemEntry * MemEntryPtr;
#endif
valgrind 说什么
$ gcc -g test.c -o test
test.c:8:26: warning: initialization from incompatible pointer type [enabled by default]
static char* memArrPtr = &memArr;
^
$ valgrind ./test
==30474== Memcheck, a memory error detector
==30474== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==30474== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==30474== Command: ./test
==30474==
==30474== Invalid write of size 8
==30474== at 0x4005FF: custom_malloc (test.c:27)
==30474== by 0x4006A3: main (test.c:49)
==30474== Address 0xfff001f90 is not stack'd, malloc'd or (recently) free'd
==30474==
==30474==
==30474== Process terminating with default action of signal 11 (SIGSEGV)
==30474== Access not within mapped region at address 0xFFF001F90
==30474== at 0x4005FF: custom_malloc (test.c:27)
==30474== by 0x4006A3: main (test.c:49)
==30474== If you believe this happened as a result of a stack
==30474== overflow in your program's main thread (unlikely but
==30474== possible), you can try to increase the size of the
==30474== main thread stack using the --main-stacksize= flag.
==30474== The main thread stack size used in this run was 8388608.
==30474==
==30474== HEAP SUMMARY:
==30474== in use at exit: 0 bytes in 0 blocks
==30474== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==30474==
==30474== All heap blocks were freed -- no leaks are possible
==30474==
==30474== For counts of detected and suppressed errors, rerun with: -v
==30474== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
valgrind 反对第 27 行的无效写入:
25 if ((curr->size - (size)) > sizeof(struct MemEntry)) {
26 MemEntryPtr newMemEntry = (MemEntryPtr) (&curr + sizeof(struct MemEntry) + size);
27 newMemEntry->prev = curr;
特别是,它说内存地址 newMemEntry->prev 无效。
回溯过去,只要newMemEntry是有效的MemEntryPtr地址,这个内存地址就应该是有效的。
But the assignment of newMemEntry is
- adding sizes aligned to sizeof char
- applying this pointer arithmetic on base pointer of type ( MemEntryPtr * ) instead of char * to match char-aligned sizes
更改代码以对基本 char * 执行指针算术,因为所有 sizeof 都是在编写时考虑到这一点,我们得到:
25 if ((curr->size - (size)) > sizeof(struct MemEntry)) {
26 MemEntryPtr newMemEntry = (MemEntryPtr) ((char *)curr + sizeof(struct MemEntry) + size);
27 newMemEntry->prev = curr;
并使用 valgrind 检查此更改:
valgrind 重新检查
$ gcc -g test.c -o test
test.c:8:26: warning: initialization from incompatible pointer type [enabled by default]
static char* memArrPtr = &memArr;
^
$ valgrind ./test
==1212== Memcheck, a memory error detector
==1212== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==1212== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==1212== Command: ./test
==1212==
3984
==1212==
==1212== HEAP SUMMARY:
==1212== in use at exit: 0 bytes in 0 blocks
==1212== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==1212==
==1212== All heap blocks were freed -- no leaks are possible
==1212==
==1212== For counts of detected and suppressed errors, rerun with: -v
==1212== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
内存使用现在正常 - 并且没有段错误
关于C 程序有时会出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33193326/