+ Responder ao Tópico



  1. #1

    Padrão Colocar uma estrutura num ponteiro void (C)

    Eawe povo.......to meio sem tempo pra ajuda o povo mas sempre q eu posso eu to ai.....se alguem puder me ajudar com isso eu com certesa vo te mais tempo pro underlinux, eh o seguinte..

    finalmente eu comecei a desenvolver em C com BerkeleyDB, estava tendo sucesso ateh cismar de armazenar uma estrutura de dados no banco, inicialmente apos mto sofrimento eu consigui armazenar uma estrutura dentro do maldito banco, tudo ordenado bunitinho, POREM, estava tudo dentro da funcao main(), agora pra ficar melhor o programa eu tive q dividir o programa em funcoes, dai eu criei uma estrutura mais ou menos assim:

    Código :
    struct{
         int id.
          char nome[150];
    } my_fields;
     
    typedef struct(
        int N;
        struct my_fields fields;
    } MY_TABLE;

    ai eu declaro uma variavel do tipo MY_TABLE como ponteiro:
    Código :
    MY_TABLE *tabela;

    dai eu faco as funcoes terem como argumento uma variavel do tipo MY_TABLE e tbm como ponteiro, assim:
    Código :
    int funcao(MY_TABLE *tabela);

    ateh ai td bem....eu manipulo a estrutura do jeito q eu quizer......soh q tem a maldita estrutura DBT que eh do proprio Berkeley, ela eh assim:
    Código :
    typedef struct {
    	void *data;
    	u_int32_t size;
    	u_int32_t ulen;
    	u_int32_t dlen;
    	u_int32_t doff;
    	u_int32_t flags;
    } DBT;

    dai pra eu armazenar alguma coisa no banco eu tenho q fazer assim:
    1° eu seto o tamanho do dado usando data.size=sizeof(tabela)+sizeof(tabela.fields);
    2° eu seto o conteudo do dado em data.data (ja previamente declarado assim: DBT data);

    soh q pra armazenar uma estrutura eu usavava o memcpy assim:
    Código :
    memcpy(&data.data,tabela,sizeof(tabela)+sizeof(tabela.fields));

    soh q depois q eu tive q separar em funcoes, essa porra paro de funciona e passo a dar falha de segmentacao :cry:

    alguem sabe o porquê??????
    Kakaroto??? chvt??? alguem?????

  2. #2
    hez4el
    Visitante

    Padrão Colocar uma estrutura num ponteiro void (C)

    E ae.

    se a variavel "tabela" é um ponteiro para a estrutura MY_TABLE
    e vc quer copiar o valor para dentro da estrutura DBT
    vc deve tentar usar operador de resgate de valor *;

    memcpy(&data.data, *tabela, sizeof(tabela)+sizeof(tabela.fields));
    Talvez seja isso;
    Abraços.

  3. #3

    Padrão Colocar uma estrutura num ponteiro void (C)

    ae, valeu hez4el, mas continuou dando falha de segmentacao quando eu rodo ele, vc nao sabe como eu poderia fazer pro ponteiro do void apontar pro mesmo endereco da memoria do ponteiro da estrutura???

    ps.: "data.data=&tabela;" nao funciona tbm... :cry: :cry:

  4. #4
    hez4el
    Visitante

    Padrão Colocar uma estrutura num ponteiro void (C)

    vc pode postar o trecho completo do código dividido em funções pra eu dar ma olhada, acho que a movimentação em memória pode estar errada em algum ponto e o ponteiro de tabela pode estar indo vazio.

    Dando uma olhada no código da pra confirmar. Essas operações
    com ponteiro em c são realmente dificieis de debugar.

    Abraços.

  5. #5

    Padrão Colocar uma estrutura num ponteiro void (C)

    o codigo em si eh isso aqui:

    Código :
    	int ret;
    	int maior;
    	//int a;
    	char nome[121];
     
    	DBT key,data; 
     
    	printf("Nome: ");
    	fgets(nome,120,stdin);
    	nome[strlen(nome)+1]='\0';
     
    	memset(&key,0,sizeof(key));
    	memset(&data,0,sizeof(data));
     
    	maior=biggest(tabela);
    	maior++;
     
    	tabela->N+=1;
    	tabela->fields[maior].id=maior;
    	strcpy(tabela->fields[maior].nome,nome);
     
    	memcpy(&data.data,&tabela,sizeof(tabela)+sizeof(tabela->fields));
    	data.size=sizeof(tabela)+sizeof(tabela->fields);
    	//data.flags=DB_DBT_MALLOC;
    	//return(0);
     
    	key.data="tabela1";
    	key.size=strlen("tabela1");
     
    	ret=db->put(db,NULL,&key,&data,0);
    	if(ret!=0){
    		printf("ERRO:\n%s\n",db_strerror(ret));
    	}else{
    		printf("Registro inserido com sucesso\n");
    	}
     
    	return(0);

  6. #6
    hez4el
    Visitante

    Padrão Colocar uma estrutura num ponteiro void (C)

    Cara eu ja reli seu código fonte de tras pra frente varias vezes,
    num consigo achar nada...
    É dureza pakas... deve ser uma bobeirinha de nada.

    Se eu achar eu dou um toque, mas até la vc ja deve ter conseguido.

    Abraços.

  7. #7

    Padrão Colocar uma estrutura num ponteiro void (C)

    eu acho q o problema eh na hora de inserir no banco com o DB->put(); o erro ta sendo nele....ai eu rodo um gdb nele e ele fala q o problema eh no memcpy, e eu acho q o put executa o memcpy...por isso to me f** aqui pra resolver isso, acho q o problema eh com o tamanho q eu num devo ta sabendo passar direito.....quando eu resolver eu falo q milagre tive q fazer :wink:

  8. #8
    fricardo
    Visitante

    Padrão Colocar uma estrutura num ponteiro void (C)

    Qualquer coisa, tenta fazer um cast pra void * do seu dado:

    Código :
    memcpy(&data.data,(void *)tabela,sizeof(tabela)+sizeof(tabela->fields));

    não vou te afirmar q a linha eh exatamente esta mas o cast pra void *, deve resolver seu problema já q (void *) quer dizer um ponteiro de tipo não especificado.

    fricardo

  9. #9

    Padrão Colocar uma estrutura num ponteiro void (C)

    Hmmm...interecante essa sua solucao, amanha eu vo testar la no trabalho, valeu

  10. #10
    hez4el
    Visitante

    Padrão Colocar uma estrutura num ponteiro void (C)

    Olá.
    Achei um outro jeito que pode ser q funcione.
    Para localizar um membro de uma estrutura em ponteiro deve-se usar "->" para indicar o membro sem precisar utilizar "&", o compilador trabalha com o ponteiro de forma amigavel.
    Eu fiz um teste mas o fragmento q eu usei nem compilou quando eu usei o "." para chamar o membro data da estrutura.
    Verifica ae se funfa.

    memcpy(data->data,&tabela,sizeof(tabela)+sizeof(tabela->fields));
    Abraços.

  11. #11

    Padrão Colocar uma estrutura num ponteiro void (C)

    mas pela variavel data nao ser um ponteiro de uma estrutura ele iria nao funcionar??
    pq eu TENHO q declarar a varivel como do tipo DBT, mas sem ser do tipo ponteiro, ou seja:
    DBT data;

    e nao

    DBT *data;

  12. #12
    hez4el
    Visitante

    Padrão Colocar uma estrutura num ponteiro void (C)

    É porque data não é ponteiro mas o membro dela data.data é
    "void *data;" então tem que ser tratado como ponteiro.

  13. #13
    fricardo
    Visitante

    Padrão Colocar uma estrutura num ponteiro void (C)

    E aeh, SDM,

    vc tentou com o cast para (void *)? Não funcionou não? Já foi tantas sugestões q a gente vai acabar ficando sem nenhuma ...

    fricardo

  14. #14

    Padrão Colocar uma estrutura num ponteiro void (C)

    eae fricado, bom cara....eu acho q ja consigui faze o void aponta pra estrutura, meu problema agora ta sendo na hora do DB->put().....agora a falha de segmentacao eh no memcpy dele....eu ja tentei da um return(0); exatamente na linha anterior ao put, e ele funcionou perfeitamente, soh q se eu colocar o return na linha seguinte, ele da erro....

    valeu Hez4el, valeu Fricado

  15. #15
    hez4el
    Visitante

    Padrão Colocar uma estrutura num ponteiro void (C)

    Ola SDM

    tem um problema no return 0;
    esse comando funciona como break dentro de uma função.

    se voce colocar por exemplo:
    return 0;
    x=1;
    o comando x=1 não sera executado porque a função para no return.
    por isso quando vc coloca ele antes do memcpy do DBT->put() funciona legalzinho, porque ele nem chega a executar.

    o certo é vc colocar depois mesmo senão tudo que vier depois ele não é executado. por isso é indicado usa-lo somente no fim da função.

    Alias vc pode explicar um trecho pra mim
    1 - o retorno de db->put é um ponteiro para int ou um int?
    2 - é db->put ou db.put?
    3 - qual o tipo de db, e quais os parametros formais da função put();

    ret=db->put(db,NULL,&key,&data,0);

    se o erro ta nessa função vm explorar todas as possibilidades dela!!!!

    Abraços

  16. #16

    Padrão Colocar uma estrutura num ponteiro void (C)

    opa, vamo la entao, bom antes de mais nada eu falei sobre ter colocado o return antes da funcao exatamente para saber onde ta o erro, como eu vi q se colocar antes do put ele retorna normal e q se eu colocar depois ele da erro, eu vi q o problema esta realmente no put (e nao na passagem de memoria, como dito anteriormente)....agora respondendo as perguntas

    1 - o retorno de db->put h um inteiro que pode ser igual a zero caso nao retorne erro, ou diferente de zero se ocorrer um erro

    2 - é db->put pois db eh um ponteiro pra uma outra estrutura (q eu ainda nao achei como eh definida), ou seja a variavel db eh declarada assim: DB *db; e eh essa variavel que vai armazenar a "conexao" com o banco de dados

    3 - o tipo foi dito acima, e os parametros sao os seguintes:
    int DB->put(DB *db,DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags);

    onde:

    DB *db - eh o ponteiro de conexao com o banco
    DB_TXN *txnid - Ainda nao entendi o que eh, mas na documentacao diz o seguinte:
    "txnid
    If the operation is to be transaction-protected, (other than by specifying the DB_AUTO_COMMIT flag), the txnid parameter is a transaction handle returned from DB_ENV->txn_begin; otherwise, NULL."

    DBT *key - eh a chave que identifica o dado pra quando eu for pega-lo do banco com o db->get()

    DBT *data - sao os dados em si, que no meu caso eh a estrutura

    u_int32_t flags - Sao flags opcionais pra identificar como vai inserido o dado, tem a opcao de nao inserir duplicado, tem de auto-commit e outras, mas no meu caso eu uso 0(zero)

  17. #17
    fricardo
    Visitante

    Padrão Colocar uma estrutura num ponteiro void (C)

    Alguns links q vc deve achar interessantes:

    http://www.sleepycat.com/docs/api_cxx/db_class.html -- Definição da classe DB
    http://www.sleepycat.com/docs/api_c/db_list.html -- lista de métodos relacionados a DB

    DB é uma classe. Um trecho do primeiro link q torna claro a relação entre esta classe e a API C do Berkeley DB está a seguir:

    -----------------------------------------
    Each Db object has an associated DB struct, which is used by the underlying implementation of Berkeley DB and its C-language API. The Db::get_DB method returns a pointer to this struct. Given a const Db object, Db::get_const_DB returns a const pointer to the same struct.

    Given a DB struct, the Db::get_Db method returns the corresponding Db object, if there is one. If the DB object was not associated with a Db (that is, it was not returned from a call to Db::get_DB), then the result of Db::get_Db is undefined. Given a const DB struct, Db::get_const_Db returns the associated const Db object, if there is one.
    ---------------------------------------

    Valeu SDM, hez4el, aprendi muito com vcs.

    fricardo

  18. #18

    Padrão Colocar uma estrutura num ponteiro void (C)

    Citação Postado originalmente por fricardo
    http://www.sleepycat.com/docs/api_cxx/db_class.html -- Definição da classe DB
    http://www.sleepycat.com/docs/api_c/db_list.html -- lista de métodos relacionados a DB
    ...
    Given a DB struct, the Db::get_Db method returns the corresponding Db object, if there is one. If the DB object was not associated with a Db (that is, it was not returned from a call to Db::get_DB), then the result of Db::get_Db is undefined. Given a const DB struct, Db::get_const_Db returns the associated const Db object, if there is one.
    ---------------------------------------
    Eae fricado, valeu, eu to me baseando nesse doc desde q comecei.....soh q como meu ingles eh fraco eu to apanhando um poco, mas msm assim valeu, e quanto a segunda parte, ela nao seria do C++?? pq o primeiro link se refere a api do c++ se nao me engano.... bom eh isso ae.....vo apanha mais um poco aqui.....e o link q eu acho q poderia resolver meu problema eh esse aqui:

    http://www.sleepycat.com/docs/ref/am_misc/struct.html

    soh q eu num to consiguindo entender mto bem....
    :cry:

  19. #19
    fricardo
    Visitante

    Padrão Colocar uma estrutura num ponteiro void (C)

    Citação Postado originalmente por SDM
    o link q eu acho q poderia resolver meu problema eh esse aqui:

    http://www.sleepycat.com/docs/ref/am_misc/struct.html

    soh q eu num to consiguindo entender mto bem....
    :cry:
    Eu vou tentar dar uma ajuda. Eu li o documento e lá ele diz q há duas maneiras de armazenar estruturas e objetos no Berkeley DB.

    A primeira está mostrada nos dois primeiros trechos de código. Esta técnica eh conhecida como "marshalling" e, basicamente vc cria uma estrutura auxiliar intermediária para transferir os dados. Vc vai preenchendo um array de bytes copiando os dados de info para data_buffer. Isto eh feito antes de armazenar no Berkeley DB. O segundo trecho de código tbm faz parte da primeira maneira de armazenar, mas ela é o "unmarshall". Repare q ele faz o contrário do primeiro código. Isto eh quando tiver q ler tudo, aí é preciso transferir o conteúdo para data_buffer e depois pra info.

    A segunda maneira de armazenar foi a q vc usou segundo o código q vc postou. Ela eh mais simples mas soh pode ser usada para o caso em q vc tem na estrutura um único campo de comprimento na estrutura como abaixo:

    Código :
    struct {
    	int a, b, c;
    	u_int8_t buf[1];
    } info;

    Todo código após esse (terceiro trecho) fala de como armazenar no BD esta struct.

    Eu só tentei te dar uma visão geral, até porque eu nao tenho muita base pra entrar mais em detalhes.

    Bom trabalho,
    fricardo