2014-09-25 3 views
1

Я создаю структуру внутри функции, а затем возвращаю ее указатель. По какой-то причине я все время получаю один и тот же адрес памяти.Структуры и указатели в C

typedef struct list_type 
{ 
    node_t *head; 
    node_t *tail; 
} list_t; 

list_t newList() { 
    list_t list = {NULL, NULL}; 
    list_t *listptr = &list; 
    printf("newList: %p\n", listptr); 
    return listptr; 
} 

Выходы:

newList: 0x7fffb42c8ae0 
newList: 0x7fffb42c8ae0 
newList: 0x7fffb42c8ae0 

Что я делаю ...

+1

Подробнее о [неопределенном поведении] (http: //en.wikipedia.орг/вики/Undefined_behavior). У тебя есть. –

+0

Во-первых, 'list_t *' не 'list_t'. Компилятор должен был как минимум предупредить вас об этом. Если это не так, повысите уровень предупреждения. – WhozCraig

+1

Этот код не должен компилироваться при возврате 'list_t *', а в определении - 'list_t'. –

ответ

2

Вы возвращающие указатель на объект, выделенного на стеке. Если вы используете значение, указываемое указателем в функции, вызывающей newList(), вы вызовете неопределенное поведение.

Вы должны прочитать о таНос() и бесплатно().

3

Вы размещаете в стеке list, но вы пытаетесь вернуть ссылку на него из функции. Это большой нет-нет в C, так как память структуры автоматически освобождается компилятором, когда она выходит за рамки. Если вы хотите, чтобы память сохранялась за пределами области, в которой она выделена, вам нужно использовать malloc.

Кроме того, list_t и указатель на него (list_t*) - это два разных типа, и вам необходимо указать, что как таковые в определении вашей функции.

list_t* newList() { 
    list_t *listptr = malloc(sizeof(list_t)); 
    printf("newList: %p\n", listptr); 
    return listptr; 
} 

Однако будьте осторожны при использовании malloc. Поскольку вы распределяете память вручную, теперь вам нужно убедиться, что вы указали free на указатель, когда закончите с ним, или он будет протекать, поскольку компилятор не может освободить память для вас.

2

Ваша функция возвращает list_t, тип структуры, который является совершенно точным по значению. Я не вижу никаких доказательств, которые вы пытаетесь динамически выделить list_t, и никаких доказательств, которые вы даже не нужно делать.

Потерять указатель материал для этой конкретной структуры типа целиком и просто сделать это:

list_t newList() 
{ 
    list_t list = {NULL, NULL}; 
    return list; 
} 

void freeList(list_t lst) 
{ 
    // TODO: delete lst nodes by walking lst.head through lst.tail 
} 

int main() 
{ 
    list_t lst = newList(); 

    ... 

    freeList(lst); 
} 

Не наступайте на арену управления динамической памятью, потому что вы можете ; сделайте это, когда вам необходимо сделать это, и в этом случае вы этого не сделаете. Вам очевидно необходимо для управления фактическим списком узлов, но это другая проблема, чем эта.

3

list_t list = {NULL, NULL}; выделяет память на стеке. Память, выделенная в стеке, автоматически освобождается, когда переменная, список в вашем случае, выходит за рамки. Вот почему вы получаете тот же адрес снова и снова, когда память, выделенная для списка в стеке, освобождается, когда программа выходит из функции newList() и доступна для выделения. И, когда вы снова назовете newList(), эта же память снова активируется.

Вы должны прочитать о различных распределениях памяти и уделять больше внимания предупреждениям компилятора.

+0

+1 за внимание больше внимания к предупреждениям компилятора. –

Смежные вопросы