我编写了函数 - malloc,free和realloc malloc函数工作正常。问题在于realloc的功能它返回了我的分段错误,我不知道为什么会发生这种情况。如果你帮助我理解为什么会发生这种情况以及如何解决它,我会很高兴。
我的代码 -
#include <unistd.h>
#include <stdio.h>
void *malloc (size_t size);
void *realloc (void *ptr, size_t size);
void free (void *ptr);
typedef struct metadata_block *p_block;
struct metadata_block
{
size_t size;
p_block next;
int free;
};
p_block head = NULL;
int
main ()
{
char *str;
int *a;
a = (int *) malloc (4);
scanf ("%d", a);
printf ("String = %d\n", *a);
a = (int *) realloc (str, 25);
scanf ("%d", a);
printf ("String = %d\n", *a);
return 0;
}
void *
malloc (size_t size)
{
void *my_malloc;
p_block tmp;
if (size <= 0)
{
return NULL;
}
if (head == NULL)
{
head = (void *) sbrk (size + sizeof (struct metadata_block));
head->size = size;
head->free = 0;
head->next = NULL;
return (void *) head + sizeof (struct metadata_block);
}
else
{
p_block tmp = head;
while (tmp->next != NULL)
{
tmp = tmp->next;
}
tmp->next = (void *) sbrk (size + sizeof (struct metadata_block));
tmp->size = size;
tmp->free = 1;
tmp->next = NULL;
return (void *) size + sizeof (struct metadata_block);
}
}
void *
realloc (void *ptr, size_t size)
{
void *newptr;
if (ptr == NULL)
{
return malloc (size);
}
if (size == 0)
{
return (ptr);
}
newptr = malloc (size);
return (newptr);
}
void
free (void *ptr)
{
p_block tmp;
if (tmp->free == 1)
{
tmp = 0;
}
ptr = NULL;
}
答案 0 :(得分:1)
你的realloc应该是这样的:
ptr == NULL
,则只需malloc
ptr != NULL
:
malloc
新尺寸的新指针(newPtr
)memcpy
内容从ptr
到newPtr
ptr
newPtr
请记住,realloc
需要一个通过调用malloc
(或NULL)给出的指针。
恕我直言,实现realloc
的行为,试图在可能的情况下返回相同的地址,这对你的任务来说太复杂了。
答案 1 :(得分:0)
OP realloc()
,我们称之为realloc_gold()
(和malloc_gold()
free_gold()
),需要复制数据内容和其他修复。
void *realloc_gold(void *ptr, size_t size) {
if (ptr == NULL) {
return malloc_gold(size);
}
当尺寸为0时,释放当前ptr
并最好处理与malloc_gold(0)
相同的方式
if (size == 0) {
free_gold(ptr);
return malloc_gold(ptr);
}
检测OOM并复制数据内容。当然这会导致问题,oldsize
是什么? C标准malloc()
,realloc()
以某种方式保存该信息 ,但用户代码通常无法访问该信息。所以这段代码需要保存它。通常的解决方案是分配请求的大小+ size_t
的大小,并将大小信息放在返回的指针之前。假设malloc_gold()
做到了。
void *newptr = malloc_gold(size);
if (newptr != NULL) {
true
size_t oldsize = ((struct metadata_block *) ptr)[-1].size;
memcpy(newptr, ptr, size < oldsize : size : oldsize);
free_gold(ptr);
}
return (newptr);
}
malloc_gold()
和free_gold()
需要考虑领先的规模 - 因此有些工作留给了OP。
答案 2 :(得分:-1)
The following is close to what you want, however, read all the commentary.
//#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void *myMalloc (size_t size);
void *myRealloc (void *ptr, size_t size);
void myFree (void *ptr);
//typedef struct metadata_block *p_block;
struct metadata_block
{
size_t size;
//p_block next;
struct metadata_block * next;
int free;
};
//p_block head = NULL;
struct metadata_block *head = NULL;
int main ()
{
//char *str;
char * str = NULL;
int *a;
//a = (int *) malloc (4);
// following is not correct because myMalloc
// returns parameter*sizeof(struct meta_block)
// probably should call system malloc() instead of myMalloc()
if( NULL == (a = myMalloc( sizeof(int) ) ) )
{ // myMalloc failed
perror("myMalloc failed");
exit( EXIT_FAILURE );
}
// implied else, myMalloc successful
//scanf ("%d", a);
if( 1 != scanf(" %d", a) )
{ // scanf failed
perror("scanf 1 failed" );
myFree( a );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf ("String = %d\n", *a);
//a = (int *) realloc (str, 25);
int * b;
if( NULL == (b = myRealloc( str, 25 ) ) )
{ // then, myRealloc failed
perror( "myRealloc failed" );
myFree(a);
exit( EXIT_FAILURE );
}
// implied else, myRealloc successful
a = b;
//scanf ("%d", a);
if( 1 != scanf(" %d", a ) )
{ // then, scanf failed
perror( "scanf 2 failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf ("String = %d\n", *a);
// <-- added following line so no memory leaks
myFree( a );
return 0;
} // end function: main
void *myMalloc (size_t size)
{
//void *my_malloc;
//p_block tmp;
if (size <= 0)
{
return NULL;
}
if (head == NULL)
{
if( NULL == (head = malloc(sizeof(struct metadata_block)*(size))) )
{ // then, malloc failed
perror( "malloc failed" );
exit( EXIT_FAILURE);
}
// implied else, malloc successful
head->size = size;
head->free = 0;
head->next = NULL;
return (void *) head + sizeof (struct metadata_block);
}
else
{
struct metadata_block* tmp = head;
// step through existing linked list
while (tmp->next != NULL)
{
tmp = tmp->next;
}
// initialize new metadata_block instance
//tmp->next = (void *) sbrk (size + sizeof (struct metadata_block));
tmp->next = malloc(sizeof(struct metadata_block)*(size+1));
tmp->size = size;
tmp->free = 1;
tmp->next = NULL;
return (void *) size + sizeof (struct metadata_block);
}
} // end function: myMalloc
void *realloc (void *ptr, size_t size)
{
void *newptr;
if (ptr == NULL)
{
return malloc (size);
}
if (size == 0)
{
return (ptr);
}
newptr = malloc (size);
return (newptr);
} // end function: realloc
// <-- the function myFree fails to actually free anything
// and tmp is being used without first being set to something
void myFree (void *ptr)
{
//p_block tmp;
struct metadata_block *tmp = ptr;
if (tmp->free == 1)
{
tmp = 0; // <-- this looses the allocated memory pointer
// without actually freeing the allocated memory
}
ptr = NULL; // <-- this has no effect on the rest of the program allocated memory
// because C passes by value, not by reference
} // end function: myFree