- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
第一篇文章,长期读者。我正在学习 C,但拥有多年的 Python 经验。抱歉,如果这是转发,但我什至不知道在谷歌搜索时使用的正确词汇。
我认为我仍然停留在面向对象的思维方式中,这导致我在 C 中遇到愚蠢的事情。我有一个类型“my_type”,其中包含指向第二个类型“my_array”的指针。按照我的 OO 思维方式,我想为 my_type 编写 New 和 Free 函数。在初始化期间,my_type 应该创建一个新的 my_array 并存储它的指针。稍后在销毁期间,my_type 的析构函数应调用 my_array 的析构函数并释放动态分配的内存。
这段代码可以编译,但会产生一个严重的错误
#include <stdio.h>
#include <stdlib.h>
/**
* @brief A type implementing a dynamically allocated array
*/
typedef struct my_array {
int n;
double *array;
} my_array;
/**
* @brief A type containing a my_array pointer
*/
typedef struct my_type {
my_array *a;
} my_type;
/**
* @brief Initialize the dynamically allocated array
*
* @param ma pointer to a my_array
* @param n number of array elements
*/
void my_array_new(my_array *ma, int n) {
ma->n = n;
ma->array = (double *) malloc(n * sizeof(double));
}
/**
* @brief Free dynamically allocated memory of a my_array
*
* @param ma pointer to a my_array
*/
void my_array_free(my_array *ma) {
free(ma->array);
}
/**
* @brief Initialize a my_type
*
* @param mt pointer to a my_type
* @param n number of array elements
*/
void my_type_new(my_type *mt, int n) {
/* Create a local my_array */
my_array a;
my_array_new(&a, n);
/* Store pointer to a */
mt->a = &a;
/* I am holding on to the pointer for a, but does a fall out of scope
* here? Is this the origin of the error? */
}
/**
* @brief Free allocated my_type
*
* @param mt pointer to my_type
*/
void my_type_free(my_type *mt) {
my_array_free(mt->a);
}
int main(int argc, char *argv[]) {
my_type mt;
int n = 10;
printf("Initializing my_type %p\n", &mt);
my_type_new(&mt, n);
printf("mt.a->n = %d\n", mt.a->n);
printf("Freeing my_type %p\n", &mt);
my_type_free(&mt);
return 0;
}
这是错误
Initializing my_type 0x7ffede7434c0
mt.a->n = 10
Freeing my_type 0x7ffede7434c0
*** Error in `./test': double free or corruption (out): 0x00007ffede7434c0 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3e5f077d9e]
/lib64/libc.so.6(cfree+0x5b5)[0x3e5f0839f5]
./test[0x400618]
./test[0x400662]
./test[0x4006da]
/lib64/libc.so.6(__libc_start_main+0xf0)[0x3e5f01ffe0]
./test[0x4004f9]
我想我知道这里发生了什么。当我调用 my_type_new 时,我创建了一个本地 my_array 变量。当函数结束时,这超出了范围,但我仍然存储了指针。现在它变得模糊了:正式分配给 mt.a 的内存是否被标记为垃圾,但我仍然可以通过取消引用指针来读出它的值?
my_type_new
创建和存储 my_array
的正确方法是什么?
我愿意接受所有建议,但由于其他原因我不能在这里使用 C++ 类。
最佳答案
这里的问题是 my_type
指向一个在堆栈上分配且不再存在的对象。因此,当您尝试释放它时,您会收到错误,因为 free
函数知道您尝试释放的内存块不是堆上可以释放的 block 。
如果您想以这种方式执行操作,初始化 my_type
实例的函数应该为 my_array
分配空间。然后,除了数组的空间之外,析构函数还应该释放该空间。具体来说:
void my_type_new(my_type *mt, int n) {
/* Create a local my_array */
mt->a = malloc(sizeof *mt->a);
my_array_new(mt->a, n);
}
void my_type_free(my_type *mt) {
my_array_free(mt->a);
free(mt->a);
}
理想情况下,您还可以在释放内存块后检查分配足够空间和 NULL
指针的错误。
我还可能提到,您可能会发现最好将这些类型的对象存储在适当的位置。换句话说,如果 my_type
始终需要 my_array
的单个实例,并且您不希望它永远为 null,那么您可以只包含 my_array
实例直接在 my_type
的结构定义中,然后初始化它。这样做的优点是可以减少您定义的对象所需的分配和释放。因此,例如,
typedef struct my_type {
my_array a;
my_type;
如果您采用这种方法,那么 my_type
的初始化程序和析构函数看起来像这样:
void my_type_new(my_type *mt, int n) {
my_array_new(&mt->a, n);
}
void my_type_free(my_type *mt) {
my_array_free(&mt->a);
}
请注意,您不再需要为 my_array
分配额外的空间,因为它直接作为 my_type
的成员包含在内。
需要注意的是,这种面向对象的方法是完全有效的。我更喜欢它,部分原因是它对于不太熟悉 C 的人来说非常熟悉。而且还因为我发现它对于组织数据和功能非常有效。
您可能对 this read 感兴趣。
关于c - 保留指向局部作用域变量的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31063282/
今天有小伙伴给我留言问到,try{...}catch(){...}是什么意思?它用来干什么? 简单的说 他们是用来捕获异常的 下面我们通过一个例子来详细讲解下
我正在努力提高网站的可访问性,但我不知道如何在页脚中标记社交媒体链接列表。这些链接指向我在 facecook、twitter 等上的帐户。我不想用 role="navigation" 标记这些链接,因
说现在是 6 点,我有一个 Timer 并在 10 点安排了一个 TimerTask。之后,System DateTime 被其他服务(例如 ntp)调整为 9 点钟。我仍然希望我的 TimerTas
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我就废话不多说了,大家还是直接看代码吧~ ? 1
Maven系列1 1.什么是Maven? Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。 核心功能 Mav
我是一名优秀的程序员,十分优秀!