Variavel Global

09/12/2007

5

Compilador BDS2006 C/C++

Sou um cara do Delphi toda a minha vida. traduzi algumas livrarias do C/C++ para o pascal, mas nunca fiz nada de aprofundado em C/C++.

No momento estou criando uma gerenciador de base de dados e pensei que o C fosse a escolha ideal pois supostamente daria aqueles microlésimos de segundos a mais nas rotinas críticas, mas estou com um problema tão básico que emperra o desenvolvimento do software. O problema se chama VARIÁVEL GLOBAL !!! *************

Na unidade DB.H está descriminado:

struct CDB {
  char szNome[255];
  WORD wTables
  char Ativo;
}

struct CDB DB;


O problema é que eu consigo acessar a variável DB na unidade DB.C sem problemas, mas quando ela é referenciada em outra unidade, como por exemplo em , TABLE.C, já os dados que estavam nela (variavel) desaparecem, por exemplo:

DB.C

#include "db.h"

void fun() 
{
  db.Ativo = 1
 }

Agora, vem isso em:

TABLE.C

include "db.h"

void Outrofun() 
{
  char Ativo;
  
  Ativo = DB:Ativo; //aqui o campo DB.Ativo já não esta com o valor 1
                            // mas sim 0, como se nunca tivesse sido setado   
 }

Qdo eu vejo no watch list do o valor da variavel DB, o compilador mostra o erro E2451 - Undefined symbol ´DB´.

Porra ! Claro que o simbolo está definido, tanto é que o programa compila e roda normalmente, mas os valores dos campos é que são simplesmente apagados qdo a variavel é referenciada em outra unidade.

POR FAVOR ALGUMA AJUDA NISSO ???[/code]


Responder

Posts

09/12/2007

Docdoc

**** linguagem cheia de artimanhas, por isso que no Delphi qdo ja tamos escrevendo o final os caras de c ainda tão no Hello World.

A solução

typedef struct {
char Nome[MAX_PATH];
WORD wTables;
STRING* szTables;
BOOL Active;
} TDB;

TDB DB;



Responder

10/12/2007

Massuda

Por favor, leia as :arrow: [url=http://forum.devmedia.com.br/viewtopic.php?t=6689]Regras do forum[/url], em especial o item 1.b.

A grande maioria das linguagens tem variáveis globais. Delphi tem, por exemplo, Application, Screen e, infelizmente, todo form que você cria.
Na unidade DB.H está descriminado:
struct CDB {
  char szNome[255];
  WORD wTables
  char Ativo;
}

struct CDB DB;
Como você declarou a variável num .H, uma instancia da variável será criada em cada arquivo que incluir esse .H. Outro problema é que C faz distinção de maiuscula/minuscula, de modo que db, dB, Db e DB são símbolos diferentes.

O correto é escreve em DB.H..
extern struct CDB DB;
...assim todo módulo que incluir o .H saberá que DB é uma variável global externa (implementada em algum outro módulo e declarar em (possivelmente) DB.C...
struct CDB DB;



Responder

13/12/2007

Docdoc

Massuda, valeu pela resposta, mas...

Sei que a linguagem é case sensitive, o erro ai no código é só de digitação, mesmo porque se vc trocar DB por db, o código já não compila.

O que se passa é que o modificador [i:e771897dd6]extern[/i:e771897dd6] não compila, pois estou tentanto fazer o programa em C, penso que extern só funciona em C++, pelo menos não tem compilado com essa directiva .

A solução acabou sendo etiquetar a estrutura dessa forma:

typedef struct _TDB {
BOOL Active;
WORD wTables;
char szNome[MAX_PATH];
STRING* szTables;
} TDB, *PDB;

TDB DB;


Assim já posso acessar a tal variável DB em outra unidade e com os dados ja setados. Mas surgiu um outro problema do c****** (caramba) !

O que se passa é que para se copiar o string szNome para outra vairável tem sido impossível, ora veja o código:

void fool() { char szDest[MAX_PATH]; char *pfonte; char *pdest; pfonte = DB.szNome; pDest = szDest; //eu tentei estas formas, uma de cada vez, compilam mas não //funcionam. O szDest continua sem os dados strcpy (szDest, DB.szNome); //<--não funciona strcat (szDest, DB.szNome); //<--não funciona while(*pfonte != ´\0´) *pdest++ = *pfonte++; //<--não funciona }


Agradeço a qualquer ajuda que me possa dar.


Responder

13/12/2007

Massuda

O que se passa é que o modificador extern não compila, pois estou tentanto fazer o programa em C, penso que extern só funciona em C++, pelo menos não tem compilado com essa directiva .
[b:fe756231f6]extern[/b:fe756231f6] funciona em C e é parte da especificação ISO C90.

Este pequeno exemplo simplificado compila e funciona sem problemas usando o compilador C/C++ que vem com o C Builder 5.
/* --- DB.H --- */

#include <stdlib.h>

typedef struct { 
   char nome[80]; 
} TDB, *PDB; 

extern TDB DB; 

/* --- DB.C --- */

include "db.h"

TDB DB; 

/* --- foo.c --- */

include <stdio.h>
include <string.h>
include "db.h"

int main(int argc, char *argv[]) {

  strcpy(DB.nome, argv[0]);
  printf("DB.nome = \"¬s\"\n", DB.nome);
  
  return(0);
}



Responder

13/12/2007

Massuda

Um exemplo (acho) melhor...
/* --- DB.H --- */ 

#include <stdlib.h>

typedef struct { 
   char nome[80]; 
} TDB, *PDB; 

extern TDB DB; 

void IniciarDB(char *ANome);

/* --- DB.C --- */ 

include <string.h>
include <mem.h>
include "db.h"

TDB DB; 

void IniciarDB(char *ANome) {

  memset(&DB, 0, sizeof(DB));
  strcpy(DB.nome, ANome);
}

/* --- foo.c --- */ 

include <stdio.h>
include "db.h"

int main(int argc, char *argv[]) {

  IniciarDB(argv[0]);
  printf("DB.nome = \"¬s\"\n", DB.nome);
  
  return(0);
}



Responder

13/12/2007

Docdoc

Massuda, novamente obrigado pela resposta.

Com a directiva [i:3b4f32b051]extern[/i:3b4f32b051] estou tendo a seguinte mensagem de erro:

[Linker Error] Error: Unresolved external ´_DB´ referenced from C:\TOOLS\CODE\C++\DOCDB\TABLE.OBJ


O compilador é o da Borland no produto BDS2006.

O outro problema é ainda mais bizarro, principalmente pra mim que venho do Delphi, ou seja, qdo tento copiar o string da estrutura para uma variavel de escopo local, nada acontece.

No código abaixo a variavel szLocal não recebe os dados do campo da estrura DB.szNome, não sei explicar isso a não ser por bug no compilador :(


    char szLocal[MAX_PATH];
    
    strcpy(szLoca, DB.szNome);



Vou tentar fazer mais alterações, mas se vocÊs tiverem alguma idéia do que tá acontecendo, agradeço ajuda.


Responder

13/12/2007

Docdoc

Caro Massuda, salve:

Reparei que no exemplo que você colocou ai em cima a variável DB foi definida na unidade DB.C, se foi assim mesmo ela só será global para a unidade onde está inserida, o restante do programa não a consegue ´enxergar´, não é mesmo ???

abraços


Responder

14/12/2007

Massuda

...se foi assim mesmo ela só será global para a unidade onde está inserida, o restante do programa não a consegue ´enxergar´, não é mesmo ???
Isso não acontece por causa do ´extern TDB DB´ que tem em DB.H. Essa linha diz a qualquer módulo que inclua esse .H que ´existe uma variável DB do tipo TDB que foi implementada em algum outro módulo´.

A variável global DB seria visível apenas em DB.C se ela tivesse sido declarada como [b:cad3f8213b]static[/b:cad3f8213b]...
static TDB DB;
...nesse caso, toda a linkagem falharia porque o símbolo DB não será encontrado.


Responder

14/12/2007

Docdoc

Caro Massuda, resumindo e concluindo.

a clausula [i:8d4097d3db]extern[/i:8d4097d3db] eu utilizo quando quero declarar uma variável de uma unidade em outra, por exemplo.

A variável int i foi declarada na unidade FUN.H, ok ?

Para utiliza-la em outra unidade tenho que declara-la novamente, nessa nova unidade, por exemplo em OUTRAUNIT.C, como [i:8d4097d3db]extern int i[/i:8d4097d3db], pois ai eu digo a unidade OUTRAUNIT.C que a variavel [b:8d4097d3db][i:8d4097d3db]int i[/i:8d4097d3db][/b:8d4097d3db] faz parte de fora dessa mesmo unidade, ok ???

Bem mas meu grande problema não tem sido isso, pois já está resolvido, já sei como declarar uma estrutura global, na minha solução passou por etiquetar a estrutura, na verdade o que não consigo copiar os dados da estrutura em outras variáveis locais, no caso concreto :



void fool()
{
char szDest[MAX_PATH];
char *pfonte;
char *pdest;

pfonte = DB.szNome;
pDest = szDest;

//eu tentei estas formas, uma de cada vez, compilam mas não
//funcionam. O szDest continua sem os dados

strcpy (szDest, DB.szNome); //<--não funciona
strcat (szDest, DB.szNome); //<--não funciona
while(*pfonte != ´\0´) *pdest++ = *pfonte++; //<--não funciona

} 


Se voce tem alguma luz sobre essa aberração eu seria eternamente grato


Responder

17/12/2007

Massuda

Mostre como voce declarou a variável DB. Em algum lugar do seu projeto (provavelmente em um arquivo .C) DB deve estar declarado [b:10dee36e31]sem[/b:10dee36e31] o extern.

O etiquetamento que você fala não tem relação com variável global.

Explique melhor o que você quer dizer com ´não funciona´.


Responder

17/12/2007

Docdoc

Mostre como voce declarou a variável DB. Em algum lugar do seu projeto (provavelmente em um arquivo .C) DB deve estar declarado [b:3cdf548edc]sem[/b:3cdf548edc] o extern. O etiquetamento que você fala não tem relação com variável global. Explique melhor o que você quer dizer com ´não funciona´.





[b:3cdf548edc]Ok, então aqui vai o bicho:[/b:3cdf548edc]



//unidade db.h

#pragma once
ifndef DB_H
define DB_H

include <windows.h>
include "estruturas.h"

typedef struct _TDB {
BOOL Active;
WORD wTables;
char szNome[MAX_PATH];
STRING* szTables;
} TDB, *PDB;

TDB DB;

endif


[b:3cdf548edc]Agora na unidade table.c[/b:3cdf548edc]


include "table.h"
#include "DB.h"

include <windows.h>
include <io.h>
include <stdio.h>
include <dir.h>
include <fcntl.h>
include <string.h>
include <malloc.h>
include <sys\stat.h>
include <stdio.h>
include <string.h>

boolean WINAPI OpenTable(STRING name)
{
  char path[MAX_PATH];
  FILE *file;

  // é aqui QUE NÃO FUNCIONA, o campo de DB.szNome não é copiado para path, simplesmente não copia, mas quando fazemos um breakpoint aqui, vemos que DB.szNome está correctamente setado para o caminho do diretorio onde está a tabla a abrir.

  strcpy(path, DB.szNome);

  //já as próximas instruções funcionam bem, o que significa que path acaba recebendo o valor do parâmetro name e depois a extensão do arquivo ".db"

  strcat(path, name);
  strcat(path, ".db");
  
  f = open(path, O_RDONLY | O_BINARY , S_IREAD | S_IWRITE);
  if (f==-1) {return false;};

  //rotina de leitura do arquivo

  close(f);

  return true;
};


[b:3cdf548edc] O Mais interessante é que tudo compila na maior ser problemas. A lógica está correcta mas algo falha redondamente, não consigo perceber o que é.

Obrigado pelas ajudas[/b:3cdf548edc]


Responder

17/12/2007

Massuda

Do jeito que está feito, sem extern, o compilador enxerga assim seu fonte table.c...
#include "table.h"

//unidade db.h

pragma once
ifndef DB_H
define DB_H

include <windows.h>
include "estruturas.h"

typedef struct _TDB {
BOOL Active;
WORD wTables;
char szNome[MAX_PATH];
STRING* szTables;
} TDB, *PDB;

TDB DB;

endif


include <windows.h>
include <io.h>
include <stdio.h>
include <dir.h>
include <fcntl.h>
include <string.h>
include <malloc.h>
include <sys\stat.h>
include <stdio.h>
include <string.h>

boolean WINAPI OpenTable(STRING name)
{
  char path[MAX_PATH];
  FILE *file;

  // é aqui QUE NÃO FUNCIONA, o campo de DB.szNome não é copiado para path, simplesmente não copia, mas quando fazemos um breakpoint aqui, vemos que DB.szNome está correctamente setado para o caminho do diretorio onde está a tabla a abrir.

  strcpy(path, DB.szNome);
...
...de modo que DB é uma variável global de table.c visível apenas dentro de table.c; não sei o que o debugger está te mostrando, mas possivelmente é um DB declarado em outro módulo, possivelmente o módulo onde vc fez a inicialização de DB.


Responder

18/12/2007

Docdoc

Po, Massuda, agora é que tô louco !

A variavel DB nunca foi declarada em table.c, somente em db.h. Só existe uma variável DB no programa todo.

Em todo o programa o debugger mostra a variável devidamente setada no caminho do diretorio onde contem a tabela, o que se passa é que essee valor não consigo passar pra variável local, sinistro ! Porém já consigo copiar das variáveis locais pra esta variável DB

Vai entender !


Responder

18/12/2007

Massuda

Não sei como é seu programa todo mas...
A variavel DB nunca foi declarada em table.c, somente em db.h. Só existe uma variável DB no programa todo.
...existe uma variável DB em cada ´unidade´ que incluir o arquivo DB.H.


Responder

18/12/2007

Massuda

...existe uma variável DB em cada ´unidade´ que incluir o arquivo DB.H.
Se estiver mesmo acontecendo isso, o linker deve(ria) gerar um warning do tipo...
Warning: Public symbol ´_DB´ defined in both module blablabla.OBJ and foobar.OBJ
...o que indica que a mesma variável publica foi definida em mais de um módulo.


Responder
×
+1 DevUP
Acesso diário, +1 DevUP
Parabéns, você está investindo na sua carreira