2015-10-20 3 views
0

У меня есть структура и функция, которая возвращает экземпляр Foo определяется следующим образом:C: Объем структуры, содержащей динамически распределенный элемент?

struct Foo 
{ 
    int a; 
    int* b;  
}; 

struct Foo makeFoo(int a, int bSize) 
{ 
    struct Foo foo; 
    foo.a = a; 
    foo.b = malloc(sizeof(int) * bSize); 
    for (int i = 0; i < bSize; ++i) 
     foo.b[i] = i; 

    return foo; 
} 

Первоначально я думал, что foo является локальным переменным и уедут, когда makeFoo возвращается, но от этого вопроса Is it safe to return a struct in C or C++? , Я знаю, что это безопасно.

Теперь мой вопрос в том, когда будет собрана память для foo? Должен ли я иметь free его имя b?

Скажем, я использую makeFoo так:

void barFunc() 
{ 
    struct Foo foo = makeFoo(3, 10); 

    printf("Foo.a = %d;\nFoo.b = [", foo.a); 
    for (int i = 0; i < 10; ++i) 
     printf("%d, ", foo.b[i]); 

    printf("\n"); 
} 

void main(int argc, char* argv) 
{ 
    barFunc(); 
} 

Когда barFunc возвращается, и я вернулся в main, в памяти foo собраны еще? Или мне нужно позвонить free(foo.b) в конце barFunc?

+2

Если у вас есть malloc, вам необходимо бесплатно его освободить. Если у вас нет бесплатной, она остается выделенной. –

+0

Остается только память для 'foo.b' или всей структуры? – 0x56794E

+0

А также хорошо ли это поведение? Или это зависит? – 0x56794E

ответ

1

Вы должны позвонить free(foo.b) самостоятельно до изменения foo в barFunc выходит за рамки. Это необязательно в функции makeFoo, потому что foo и указатель на выделенную память копируется в вызывающий, поэтому все в порядке.

Поскольку у вас есть makeFoo функцию, было бы хорошей практикой иметь deleteFoo функцию тоже:

void deleteFoo(struct Foo *foo) 
{ 
    free(foo->b); 
} 

void barFunc() 
{ 
    struct Foo foo = makeFoo(3, 10); 
    ... 
    deleteFoo(&foo); 
} 
+0

№ См. ответ @Felix Palman - возврат структуры копирует содержимое этой структуры, поэтому значение указателя передается вызывающему, которое может иметь дело с вызовом 'free()'. –

+0

Я думаю, что я говорю то же самое. – ChronoTrigger

+0

«Вы должны позвонить бесплатно (foo.b) самостоятельно, прежде чем переменная foo в barFunc выходит из области видимости». - Нет, указатель на память 'malloc()' 'd возвращается вызывающему, потому что структура возвращается. Значение указателя копируется в 'struct Foo' вызывающего абонента и может быть' free() ''d вызывающим.Это точно так же, как передача только указателя - копия указателя выходит из области видимости в функции выделения, также, но возвращается значение. –

2

Сначала я думал, что Foo является локальной переменной и уеду, когда makeFoo возвращается , но из этого вопроса Безопасно ли возвращать структуру на C или C++? Я знаю, что это безопасно.

Вы сделать понимают местный foo в самом деле ушел? возвращая struct по значению, как вы делаете здесь только копирует его содержимое в случай, предусмотренный вызывающей сторона. (*)

Но, конечно же, содержание включает указатель, указывающий на какую память вы наделенный malloc(). Таким образом, это должно быть free() d позже.

(*) Этот может быть хорошей идеей для небольших структур, в зависимости от ваших потребностей, но всегда имейте в виду, что все содержимое скопировано - это определенно не то, что вы хотите для какой-либо крупной структуры.

-1

Да Безопасно ли возвращать структуру из функции C/C++, но структура с большими статическими данными, так как struct fooo{int a[1024*1024*1024];}; может привести к сбою программы. поэтому гораздо безопаснее возвращать указатель на выделенный блок памяти для подобных структур.

+0

Это не «правильный путь». Возвращение структуры по значению совершенно легально и четко определено - то же самое, что возврат только указателя по значению является совершенно законным и четко определенным. –

+0

Ну, а не мой нисходящий, но идеализированный, возвращающий структуру, абсолютно безопасен (но потенциально неэффективен, если структура не так мала для такого рода вещей) –

+0

Я не верю, что ошибался: o. – milevyo