我正在学习C(阅读Sam的《24小时自学C》)。我已经了解了指针和内存分配,但现在我想知道它们在结构体中的作用。
我写了下面的小程序来玩,但我不确定它是否可以。在带有-Wall
标志的gcc的Linux系统上编译,没有任何错误,但我不确定这是100%值得信赖的。
是否可以改变指针的分配大小,就像我在下面做的那样,或者我可能会踩在相邻的内存上?我在结构中做了一点之前/之后的变量来尝试检查这一点,但不知道这是否有效,如果结构元素连续存储在内存中(我猜是这样的,因为指向结构的指针可以传递给函数,并通过指针位置操纵结构)。此外,我怎么能访问指针位置的内容,并通过它迭代,所以我可以确保没有被覆盖,如果它是连续的?我想我要问的一件事是,我怎么能调试混乱的内存这种方式知道它没有破坏任何东西?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct hello {
char *before;
char *message;
char *after;
};
int main (){
struct hello there= {
"Before",
"Hello",
"After",
};
printf("%ldn", strlen(there.message));
printf("%sn", there.message);
printf("%dn", sizeof(there));
there.message = malloc(20 * sizeof(char));
there.message = "Hello, there!";
printf("%ldn", strlen(there.message));
printf("%sn", there.message);
printf("%s %sn", there.before, there.after);
printf("%dn", sizeof(there));
return 0;
}
我认为有些事情是不对的,因为我的there
的大小没有改变。kj
亲切的问候,
不是很好,您有内存泄漏,您可以使用valgrind在运行时(在Linux上)检测它。
你正在编码:
there.message = malloc(20 * sizeof(char));
there.message = "Hello, there!";
第一个赋值调用malloc(3)。首先,当调用malloc
时,您应该始终测试它是否失败。但事实上,它通常会成功。所以最好的代码是:
there.message = malloc(20 * sizeof(char));
if (!there.message)
{ perror("malloc of 20 failed"); exit (EXIT_FAILURE); }
第二个赋值将常量字面值字符串"Hello, there!"
的地址放入同一个指针there.message
中,并且丢失了第一个值。你可能需要复制常量字符串
strncpy (there.message, "Hello, there!", 20*sizeof(char));
(可以直接使用strcpy(3),但要注意缓冲区溢出)
您可以使用strdup(3) (GNU libc也有asprintf(3)…)获得一些字符串的新副本(在堆中)
there.message = strdup("Hello, There");
if (!there.message)
{ perror("strdup failed"); exit (EXIT_FAILURE); };
最后,在程序结束时对堆内存进行free
是很好的尝试。(但是操作系统会在_exit(2)时刻抑制进程空间。
阅读更多关于C编程,内存管理,垃圾收集。也许可以考虑使用Boehm的保守GC
一个C指针只是一个内存地址区。应用程序需要知道它们的大小。
<一口> p。C语言中的手动内存管理是很棘手的,即使对于经验丰富的程序员也是如此。一口>
there.message = "Hello, there!"
不将字符串复制到缓冲区中。它将指针设置为一个新的(通常是静态的)缓冲区,其中包含字符串"Hello, there!"。因此,编写的代码存在内存泄漏(分配的内存在程序退出之前永远不会被释放)。
但是,是的,malloc本身就很好。您通常会使用strncpy、sprintf或类似的函数将内容复制到这样分配的缓冲区中。
是否可以更改指针的分配大小[…]] ?
啊?你所说的"改变指针的分配大小"是什么意思?目前你所有的代码都是通过给指针分配一个不同的地址来泄漏你malloc()
所占用的20个字节。