• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

filipemm

Memória e vectores

16 mensagens neste tópico

Boas...

As funções vector_delete e vector_set devem libertar a memória do vector e dar novos valores ao vector, como indicado nos comentários...

A vector_delete penso que está certa, mas a vector_set dá erro...

Sugestões de correcção?

/* Incluir os headers do sistema necessários */
#include <stdlib.h>
#include <stdio.h>

/* Incluir o nosso header */
#include "vector.h"

/* Definir a nossa struct para os vectores */
struct _vector_t {
size_t size;
int *data;
};

/* Criar um novo vector com tamanho 1*/
vector_t *vector_new() {
vector_t *retval;  

/* Temos que primeiro alocar memória para a nossa estrutura de dados */
retval = (vector_t *)malloc(1 * sizeof(vector_t));

/* Verificar o valor devolvido para ter a certeza que obtivemos a memória pedida */
if(retval == NULL)
	return NULL;

/* Temos agora que inicializar os dados */
retval->size = 1;
retval->data = (int *)malloc(retval->size * sizeof(int));

/* Verificar o valor devolvido para ter a certeza que obtivemos a memória pedida */
if(retval->data == NULL) {
	free(retval);
	return NULL;
}

retval->data[0] = 0;

/* Note que 'retval->size' poderia escrever-se '(*retval).size', 
 * mas a notação '->' é mais prática
 */

/* e terminamos com o ponteiro para o que se criou... */
return retval;
}

/* Libertar a memória alocada para o vector passado à função */
void vector_delete(vector_t *v) {
/* Não esquecer, tem que libertar TODA a memória que está alocada para este vector*/

/* --- ESCREVA O SEU CÓDIGO AQUI --- */

free(v->data);
free(v);
}

/* Devolver o valor de um elemento do vector */
int vector_get(vector_t *v, size_t loc) {

/* Se foi passado um ponteiro NULL pointer para o vector
 * protestar e devolver 0.
 */
if(v == NULL) {
	fprintf(stderr, "vector_get: passed a NULL vector.  Returning 0.\n");
	return 0;
}

/* Se a posição do elemento pretendido for maior que o tamanho alocado
 * devolver 0, senão devolver o valor do elemento pretendido.
 */
if(loc < v->size) {
	return v->data[loc];
} else {
	return 0;
}
}

/* Colocar um valor no vector */
void vector_set(vector_t *v, size_t loc, int value) {
/* vector deve ter um comportamento dinâmico, aceitando sempre mais elementos.
 * O que fazer quando a localização do elemento a colocar é maior que o tamanho já alocado?
 * Não esquecer que elementos não inicializados devem ficar a 0.
 */

/* --- ESCREVA O SEU CÓDIGO AQUI --- */
int i, x, k, temp[1000];

if (loc >= v->size)
{
	for (x = 0; x < loc; x++)
		temp[x] = 0;

	for (i = 0; i < loc; i++)
		temp[i] = v->data[i];

	free(v->data);

	v->data = (int *)malloc(loc * sizeof(int));

	for (k = 0; k < loc; k++)
		v->data[k] = temp[k];

	v->data[loc] = value;
}
else
{
	v->data[loc] = value;
}	
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

E usares o realloc? Poupava-te muito trabalho, e devia ser mais eficiente...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

E usares o realloc? Poupava-te muito trabalho, e devia ser mais eficiente...

Não posso, o prof não deixa!

Temos mesmo que usar o malloc()...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Primeiro aloca o espaço para o temp. Depois usa um memcpy (ou também podes copiar os valores à mão) para copiar os dados do antigo vector. Depois coloca a 0 as posições que não existiam no vector antigo (podes usar o memset aqui). Por último coloca o novo valor no devido lugar.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Primeiro aloca o espaço para o temp. Depois usa um memcpy (ou também podes copiar os valores à mão) para copiar os dados do antigo vector. Depois coloca a 0 as posições que não existiam no vector antigo (podes usar o memset aqui). Por último coloca o novo valor no devido lugar.

Penso que não é necessário alocar espaço para o temp porque é só um array temporário com tamanho fixo...

De resto, fiz como disseste: meti todas as posições do temp a 0, copiei os valores do vector para temp, libertei o v->data e aloquei-o novamente, agora com o tamanho pretendico (loc) e por fim, voltei a copiar os valores do temp para o v->data, agora com o novo espaço... e claro, atribui o novo valor (value) a v->data...

Estou a pensar de forma correcta?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Pareceu-me que à pouco o temp era apenas um apontador.

O que estás a fazer é estúpido. Copias os valores para o temp, e depois copias para o novo array.

Por que é que não copias directamente para o novo array? Isto é, por que não fazes logo:

temp=(int *)malloc(loc * sizeof(int));

e no final apenas fazes

v->data=temp;

??

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Pareceu-me que à pouco o temp era apenas um apontador.

E era, mudei para não estar a alocar mais memória :D

O que estás a fazer é estúpido. Copias os valores para o temp, e depois copias para o novo array.

Por que é que não copias directamente para o novo array? Isto é, por que não fazes logo:

temp=(int *)malloc(loc * sizeof(int));

e no final apenas fazes

v->data=temp;

??

Não percebi muito bem, mas de qualquer maneira tenho que colocar a 0 os elementos sem valor e não sei se dará como estás a pensar...

Anyway, o que eu fiz não está correcto??

Devia funcionar, certo??

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Deve funcionar.

Pois, mas o problema é esse, não funciona!!!

Todas as outras funções estão correctas mas quando chega ao vector_set dá 'barraca' :X

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

E o que é dar barraca?

testar vector_new()

testar vector_delete()

vector_new() novamente

Estes devem dar todos 0 (vector_get()): 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Testar um conjunto de vector_set()s

*** glibc detected *** ./vector.exe: free(): invalid next size (fast): 0x0978d008 ***

======= Backtrace: =========

/lib/tls/i686/cmov/libc.so.6[0x400a1454]

/lib/tls/i686/cmov/libc.so.6(cfree+0x96)[0x400a34b6]

./vector.exe[0x804862d]

./vector.exe[0x80489c3]

/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0x40048685]

./vector.exe[0x8048421]

======= Memory map: ========

08048000-08049000 r-xp 00000000 08:05 418683    /home/morais/AC/lab3/vector.exe

08049000-0804a000 r--p 00000000 08:05 418683    /home/morais/AC/lab3/vector.exe

0804a000-0804b000 rw-p 00001000 08:05 418683    /home/morais/AC/lab3/vector.exe

0976c000-097af000 rw-p 0976c000 00:00 0          [heap]

40000000-4001a000 r-xp 00000000 08:05 114526    /lib/ld-2.8.90.so

4001a000-4001b000 r-xp 4001a000 00:00 0          [vdso]

4001b000-4001c000 r--p 0001a000 08:05 114526    /lib/ld-2.8.90.so

4001c000-4001d000 rw-p 0001b000 08:05 114526    /lib/ld-2.8.90.so

4001d000-40020000 rw-p 4001d000 00:00 0

40020000-4002d000 r-xp 00000000 08:05 114476    /lib/libgcc_s.so.1

4002d000-4002e000 r--p 0000c000 08:05 114476    /lib/libgcc_s.so.1

4002e000-4002f000 rw-p 0000d000 08:05 114476    /lib/libgcc_s.so.1

40032000-4018a000 r-xp 00000000 08:05 133649    /lib/tls/i686/cmov/libc-2.8.90.so

4018a000-4018c000 r--p 00158000 08:05 133649    /lib/tls/i686/cmov/libc-2.8.90.so

4018c000-4018d000 rw-p 0015a000 08:05 133649    /lib/tls/i686/cmov/libc-2.8.90.so

4018d000-40191000 rw-p 4018d000 00:00 0

40200000-40221000 rw-p 40200000 00:00 0

40221000-40300000 ---p 40221000 00:00 0

bfb5f000-bfb74000 rw-p bffeb000 00:00 0          [stack]

make: *** [test] Aborted

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O único erro que vejo aí, é no if, pois devias ter um >= em vez de >. Assim estarás a inserir o valor fora da memória alocada. Mas não me parece que o erro venha daí.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O único erro que vejo aí, é no if, pois devias ter um >= em vez de >. Assim estarás a inserir o valor fora da memória alocada. Mas não me parece que o erro venha daí.

Pois, já alterei isso...

Mas continuo com o mesmo problema :X

Será disto: '*** glibc detected *** ./vector.exe: free(): invalid next size (fast): 0x0978d008 ***' ??

Any help?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Penso que tens isto mal.

      for (i = 0; i < loc; i++)
         temp[i] = v->data[i];

O loc vai ser sempre maior que o tamanho do que o array. Portanto o que queres é

      for (i = 0; i < v->size; i++)
         temp[i] = v->data[i];

E não te esqueças de actualizar o valor do size após a realocação da memória.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já está resolvido!! :confused::D

O problema estava no malloc() do v->data, pois estava a alocar menos memória do que era necessário...

Assim sendo, fica:

v->data = (int *)malloc((loc + 1) * sizeof(int));

Obrigado a todos pela ajuda :D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora