我正在尝试学习C的基础知识,但我无法完全让malloc()
和free()
工作。
这是我的代码,它将根据输入在屏幕中央打印一个单词。(删除了一些声明并包含以缩短它)
char *bridge_text;
char menu1[] = "Key input: nt n. car arrive north
nt s. car arrive south
nt r. empty bridge
nt q. quit";
int main()
{
bridge_text = malloc(sizeof(char)*(LEN+1)); //misprinted here before
initscr();
getmaxyx(stdscr,row, col);
mvprintw(2, 4, menu1);
refresh();
while(run)
{
switch(getchar())
{
case 'q':
run = 0;
break;
case 'n':
/*not shown: char north[] = "NORTH";*/
bridge_text = north;
break;
case 's':
bridge_text = south;
break;
case 'r':
bridge_text = empty;
break;
default:
bridge_text = empty;
break;
}
mvprintw(row/2, (col-5)/2, bridge_text);
refresh();
}
endwin();
/* adding free() here results in core dump. */
free(bridge_text);
return 0;}
我将gcc与cygwin一起使用,程序执行正确,我可以使用"q"-键退出程序,但是。。。
- 如果首先按下
'n'
、'e'
或'r'
(为bridge_text
分配字符串)然后尝试退出,会导致核心转储。如果我删除free()
使用cygwin运行可执行文件时,我确实遇到了一个错误:*
致命错误MapViewOfFileEx共享5'(0x66)Win 32错误6。
也许这就是问题所在,但我认为这与此无关。
问题
sizeof(LEN+1)
将计算为整数大小- 分配字符串时,动态分配的内存丢失
更改
bridge_text = malloc(sizeof(LEN+1));
至
bridge_text = malloc(LEN + 1);
使用strcpy
而不是分配bridge_text = north
strcpy(bridge_text, north);
进行时
bridge_text = north;
和simmilar赋值,则覆盖malloc()
返回的实际指针。现在,使用非动态分配的指针(内存)调用free()
是未定义的行为。如果你愿意,你可以参考这个答案来了解详细信息。
实际上,要将内容复制到已分配的内存中,您可以(也应该)使用strcpy()
。否则,通过分配,您也会造成内存泄漏,因为原始指针会丢失。
然后,
bridge_text = malloc(sizeof(LEN+1));
也是错误的。你需要把它改成
bridge_text = malloc(LEN+1); //sizeof(char) is 1 in c
之后,也不要忘记检查malloc()
是否成功。
不能在非动态分配的指针上调用free()
。
当您执行bridge_text = north;
时,您的malloc()
'd将丢失
bridge_text
被声明为char *
。这不像其他语言那样是一个字符串类,它只是指向某个内存的指针,该内存将作为char
s的序列读取。
通过将其他值分配给bridge_text
,您已经丢失了它的原始值(因此泄露了malloc
'd的内存),并将其指向内存的另一部分。这就是为什么当您尝试free(bridge_text)
时程序崩溃的原因——指针不再适用于释放。
此外,顺便说一句,sizeof
运算符会获得您传递的任何字节的字节大小——在本例中,可能是一个整数常量——因此您实际上只分配了5或9个字节(取决于系统),而不是(LEN + 1)
。
你有很多选项来修复你的代码:
- 不要动态分配
char
缓冲区。将声明更改为char bridge_text[LEN + 1]
,并删除malloc
和free
调用。然后使用strcpy
来填充数据 -
只需使用bridge_text作为指向包含要打印项目的其他缓冲区的指针。如果一切都是恒定的,或者你把任何动态的东西放在一个单独的缓冲区中(但不要忘记确保你的动态缓冲区不会超出范围),例如
char dynamic_string [50]; int value = 10; sprintf(dynamic_string,"Value = %d", value); bridge_text = dynamic_string;
-
继续按原样使用,但解决
malloc
大小问题,并将bridge_text = <something>
更改为strcpy(bridge_text,<something>)
。
这类线路:
bridge_text = north;
不会将north[]中的文本字符串复制到char数组bridge_text[]中。
它只复制指针。。
建议:
strcpy( bridge_text, north );
在当前代码中,bridgetext中的malloc'd指针被赋值语句覆盖。
这就是free()导致中止的原因。
建议使用"strcpy()"将字符串复制到bridge_text指向的位置