Первый пост, долго читатель. Я изучаю C, но из многолетнего опыта работы с Python. Извините, если это repost, но я даже не знаю, какой правильный словарь использовать при поиске в Google.Сохранение указателей на локальные переменные области
Я думаю, что я все еще застрял в объектно-ориентированном мышлении, что приводит меня к глупости в C. У меня есть тип «my_type», который содержит указатель на второй тип «my_array». В моем мышлении OO я хочу писать новые и бесплатные функции для my_type. Во время инициализации 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++ здесь по другим причинам.
Стандартное предупреждение: не накладывайте 'void *' как возвращаемые 'malloc' и друзьями указатели. – Olaf
[Я делаю результат 'malloc'?] (Http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Sebivor