我在C中存在内存释放问题。没有功能划分,一切都很好,但不幸的是它不能用于相同的功能。这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct {
char *name;
enum {
summer,
winter
} index;
} student;
bool init(student *s) {
printf("The next stage in the allocation of memory\n");
s = (student*)malloc(sizeof(*s));
if (&s == NULL) {
printf("Allocation Failed\n");
return 0;
} else {
printf("Allocation completed successfully\n");
}
}
void delete(student *s) {
if (&s != NULL) {
printf("begin removal\n");
free(s);
printf("Released memory");
}
}
int main() {
student *s;
init(s);
delete(s);
return 0;
}
我不知道我做错了什么。请帮忙。
答案 0 :(得分:1)
首先,函数init
具有未定义的bbehaviour,因为在成功分配内存的情况下它不会返回任何内容。
您可以通过返回指向已分配内存的指针或NULL
来检查内存是否已分配。
此声明
if(&s==NULL){
错了。条件总是会产生错误,因为局部变量s
的地址不等于NULL
。
因此可以通过以下方式重写该函数
student * init()
{
printf("The next stage in the allocation of memory\n");
student *s = ( student* )malloc( sizeof( *s ) );
if ( s == NULL )
{
printf("Allocation Failed\n");
}
else
{
printf("Allocation completed successfully\n");
}
return s;
}
并称之为
int main( void )
^^^^^
{
student *s = init();
//...
或者可以通过以下方式定义
int init( student **s )
{
printf("The next stage in the allocation of memory\n");
*s = ( student* )malloc( sizeof( **s ) );
int success = *s != NULL;
if ( !success )
{
printf("Allocation Failed\n");
}
else
{
printf("Allocation completed successfully\n");
}
return success;
}
并调用
int main( void )
^^^^^
{
student *s;
init( &s );
//...
函数delete
应至少定义为
void delete(student *s) {
if (s != NULL) {
^^^
printf("begin removal\n");
free(s);
printf("Released memory");
}
}
答案 1 :(得分:0)
首先,free是NULL安全的。如果变量已经是NULL,基本上没有任何反应。您不必检查它是否为NULL。 (您可以查看第313页ISO-IEC 9899)
此外,初始化student->name
并分配时,会出现内存泄漏。你也必须释放它。
所以,你的删除功能可能是这样的;
void delete(student *s) {
printf("begin removal\n");
free(s->name);
free(s);
printf("Released memory");
}
if (&s == NULL)
错了。必须使用if (s == NULL)
更改它们。
你的分配可能会给大代码带来很大的麻烦。如果您分配s = (student*)malloc(sizeof(*s));
,则表示&#34;分配大小为* s&#34;的s。但是指针大小是固定的内存块(大多是8个字节)。这意味着您阻止了一定大小的内存。如果你有比这更大的结构,这种分配将破坏内存,你的可执行文件将被操作系统杀死(你可以尝试在你的结构中添加更多的变量并初始化它们)。在小结构和非常短的运行时间中,大多数这种分配也有效。但我保证这对于运行时来说是不安全的。它不会在编译时发出任何警告或错误。真正的方式是s = malloc(sizeof(student))
。通过这种方式,您可以精确地分配所有内存块。并且您的记忆在运行时保持安全。
最后,您的init
函数应该返回初始化变量。你的init函数可能是这样的;
#define NAME_LENGHT 128
...
student * init(student *s) {
printf("The next stage in the allocation of memory\n");
s = malloc(sizeof(student));
if (s == NULL) {
printf("Allocation Failed\n");
return NULL;
}
s->name = malloc(NAME_LENGHT);
if (s->name == NULL) {
printf("Allocation Failed\n");
return NULL;
} else {
printf("Allocation completed successfully\n");
}
//alternatively you can strdup directly without any allocation
// s->name = strdup("some name");
return s;
}
答案 2 :(得分:-3)
您永远不会更改s
中的main
。
解决方案1:将main
中的变量指针传递给init
以填充。
void init_student(student** s_ptr) {
*s_ptr = (student*)malloc(sizeof(student));
if (*s_ptr == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
(*s_ptr)->name = malloc(MAX_NAME_SIZE + 1);
if ((*s_ptr)->name == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
(*s_ptr)->name[0] = 0;
(*s_ptr)->gpa = 0;
}
void delete_student(student* s) {
free(s->name);
free(s);
}
int main() {
student* s;
init_student(&s);
delete_student(s);
return 0;
}
解决方案1b:相同,但更清洁。
void init_student(student** s_ptr) {
student* s = (student*)malloc(sizeof(student));
if (*s_ptr == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
s->name = malloc(MAX_NAME_SIZE + 1);
if (s->name == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
s->name[0] = 0;
s->gpa = 0;
*s_ptr = s;
}
void delete_student(student* s) {
free(s->name);
free(s);
}
int main() {
student* s;
init_student(&s);
delete_student(s);
return 0;
}
解决方案2:将分配的点返回main
。
student* init_student() {
student* s = (student*)malloc(sizeof(student));
if (s == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
s->name = malloc(MAX_NAME_SIZE + 1);
if (s->name == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
s->name[0] = 0;
s->gpa = 0;
return s;
}
void delete_student(student* s) {
free(s->name);
free(s);
}
int main() {
student* s = init_student();
delete_student(s);
return 0;
}
请注意&s == NULL
永远不会成立,因为&s
是变量本身的地址。您只需要s == NULL
检查s
中指针的值。