2014-10-08 2 views
0

Я полностью готов сказать, что я делаю что-то глупое/неправильное; это то, что я ожидаю.Указатели на структуры, изменяющие значения, необъяснимые

Я получаю представление о структурах и приступает к обработке, когда дело доходит до доступа к полям из указателей. Код для подражания.

matrix.h:

#ifndef MATRIX_H_INCLUDED 
#define MATRIX_H_INCLUDED 

#include <stdlib.h> 

typedef struct 
{ 
    size_t size; 
    int* vector; 
} vector_t; 

#endif // MATRIX_H_INCLUDED 

main.c:

#include <stdio.h> 
#include <stdlib.h> 

#include "matrix.h" 

vector_t* vector_new(size_t size) 
{ 
    int vector[size]; 
    vector_t v; 
    v.size = size; 
    v.vector = vector; 
    return &v; 
} 

int main(int argc, char* argv[]) 
{ 
    vector_t* vec = vector_new(3); 
    printf("v has size %d.\n", vec->size); 
    printf("v has size %d.\n", vec->size); 

    return EXIT_SUCCESS; 
} 

Так что это очень простая программа, где я создать векторную структуру размером 3, возвращают указатель на структуру и затем напечатайте его размер. Это, в первом экземпляре печати, 3, который затем изменяется на 2686668 на следующей распечатке. Что происходит?

Заранее спасибо.

+0

Я бы предложил вместо этого создать его с созданием и распределением структуры сначала, а затем передать указатель на функцию init, которая принимает указатель созданной структуры, вводит ее и недействителен (модифицирует элементы структуры, обозначенной от указателя, а не пытаться создать структуру внутри функции). –

+0

новая функция слишком болезненна ... худший способ сделать это, она даже не ремонтируется. вы должны malloc блок вместо этого. ваша проблема вызвана стеком. адрес, который вы возвращаете, находится в стеке, однако эта часть стека используется 'printf', т. е. данные повреждены. – HuStmpHrrr

ответ

1

Вы возвращаете указатель на локальную переменную v от vector_new. Это не имеет ни малейшего шанса на работу. К моменту, когда vector_new вернется к main, все локальные переменные будут уничтожены, а ваш указатель указывает на никуда. Кроме того, память v.vector указывает на также локальный массив vector. Он также разрушается, когда возвращается vector_new.

Вот почему вы видите мусор, напечатанный вашим printf.

Ваш код должен быть полностью переработан в отношении управления памятью. Фактический массив должен быть распределен динамически, используя malloc. Сам объект vector_t может быть выделен динамически или может быть объявлен как локальная переменная в main и передан для инициализации vector_new. (Какой подход вам нужен, зависит от вас).

Например, если мы решим сделать все, используя динамическое выделение, то это может выглядеть следующим образом

vector_t* vector_new(size_t size) 
{ 
    vector_t* v = malloc(sizeof *v); 
    v->size = size; 
    v->vector = malloc(v->size * sizeof *v->vector); 
    return v; 
} 

(и не забудьте проверить, что malloc удалось).

Однако все, что мы выделили динамически, мы должны освободить позже, используя free. Итак, вам нужно будет написать функцию vector_free для этой цели.

+0

Большое спасибо. Это в основном все, что мне нужно знать, чтобы написать все мои функции. –

0

Complete переписывают ответа на Ваш вопрос, и обеспечить альтернативный подход:

Код, как написано в ОП не будет компилироваться: & v нелегальный возвращаемое значение.

Если я изменить свой код, например:

#include <stdlib.h> 
#include <stdio.h> 
#include <stdlib.h> 

typedef struct 
{ 
    size_t size; 
    int* vector; 
} vector_t; 

vector_t* vector_new(size_t size) 
{ 
    int vector[size]; 
    vector_t v, *pV; 
    pV = &v; 
    pV->size = size; 
    pV->vector = vector; 
    return pV; 
} 

int main(int argc, char* argv[]) 
{ 
    vector_t* vec = vector_new(3); 
    printf("v has size %d.\n", vec->size); 
    printf("v has size %d.\n", vec->size); 
    getchar(); 

    return EXIT_SUCCESS; 
} 

Он строит и работает, но возвращает непредусмотренные значения vec-> размер в main() из-за локальной области видимости этой переменной в функции vector_new.

Рекомендуют создания глобально видимый экземпляр вашей структуры, и переопределить vector_new() к int initVector(void):

#include <stdlib.h> 
#include <stdio.h> 
#include <stdlib.h> 

#define SIZE 10 

typedef struct 
{ 
    size_t size; 
    int* vector; 
} vector_t; 
vector_t v, *pV;//globally visible instance of struct 

int initVector(void) 
{ 
    int i; 
    pV->size = SIZE; 
    pV->vector = calloc(SIZE, sizeof(int)); 
    if(!pV->vector) return -1; 
    for(i=0;i<SIZE;i++) 
    { 
     pV->vector[i] = i; 
    } 
    return 0; 
} 

int main(int argc, char* argv[]) 
{ 
    int i; 
    pV = &v; //initialize instance of struct 
    if(initVector() == 0) 
    { 
     printf("pV->size has size %d.\n", pV->size); 
     for(i=0;i<SIZE;i++) printf("pV->vector[%d] == %d.\n", i, pV->vector[i]); 
    } 
    getchar(); //to pause execution 

    return EXIT_SUCCESS; 
} 

Урожайность эти результаты:

enter image description here

Вам все еще нужно написать функцию freeVector, чтобы отменить все выделенной памяти.

+0

'malloc (10)' плохо, даже для демонстрации ... – HuStmpHrrr

+0

@HuStmpHrrr - :), да, это было. – ryyker

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