Variavel Global
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:
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:
Agora, vem isso em:
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]
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]
Docdoc
Curtidas 0
Respostas
Docdoc
09/12/2007
**** 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
A solução
typedef struct { char Nome[MAX_PATH]; WORD wTables; STRING* szTables; BOOL Active; } TDB; TDB DB;
GOSTEI 0
Massuda
09/12/2007
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.
O correto é escreve em DB.H.....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...
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:
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.struct CDB { char szNome[255]; WORD wTables char Ativo; } struct CDB DB;
O correto é escreve em DB.H..
extern struct CDB DB;
struct CDB DB;
GOSTEI 0
Docdoc
09/12/2007
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:
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:
Agradeço a qualquer ajuda que me possa dar.
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.
GOSTEI 0
Massuda
09/12/2007
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); }
GOSTEI 0
Massuda
09/12/2007
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); }
GOSTEI 0
Docdoc
09/12/2007
Massuda, novamente obrigado pela resposta.
Com a directiva [i:3b4f32b051]extern[/i:3b4f32b051] estou tendo a seguinte mensagem de erro:
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 :(
Vou tentar fazer mais alterações, mas se vocÊs tiverem alguma idéia do que tá acontecendo, agradeço ajuda.
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.
GOSTEI 0
Docdoc
09/12/2007
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
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
GOSTEI 0
Massuda
09/12/2007
...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;
GOSTEI 0
Docdoc
09/12/2007
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 :
Se voce tem alguma luz sobre essa aberração eu seria eternamente grato
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
GOSTEI 0
Massuda
09/12/2007
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´.
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´.
GOSTEI 0
Docdoc
09/12/2007
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]
GOSTEI 0
Massuda
09/12/2007
Do jeito que está feito, sem extern, o compilador enxerga assim seu fonte table.c......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.
#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); ...
GOSTEI 0
Docdoc
09/12/2007
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 !
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 !
GOSTEI 0
Massuda
09/12/2007
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.GOSTEI 0
Massuda
09/12/2007
...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.GOSTEI 0
Docdoc
09/12/2007
:D[color=red:132882bb9e][size=18:132882bb9e]EUREKA !!! [/size:132882bb9e][/color:132882bb9e]:D
[color=red:132882bb9e][size=18:132882bb9e]ATÉ QUE ENFIM A SOLUÇÃO[/size:132882bb9e][/color:132882bb9e]
Antes de mais quero agradecer ao Massuda pela ajuda.
Bem, se vc´s se lembram do problema...eu tinha uma variável global que era uma estrutura e que não conseguia copiar seus dados para outras variáveis locais dentro das funções. Pois bem, agora já consigo e porquê ?
Quando declarei a variável [b:132882bb9e]TDB DB[/b:132882bb9e] fí-lo em [b:132882bb9e]db.h[/b:132882bb9e] e me causou todos esses transtornos, porém ao declará-la em [b:132882bb9e]db.c[/b:132882bb9e], tudo acabou por se acertar, ou seja, a variável global passou a ser copiável para outras variáveis locais, ou seja, a variável somente esta totalmente acessível quando declarada em [b:132882bb9e]db.c[/b:132882bb9e].
Quando ela estava declarada em db.h o processador aceitava a compilação mas não permitia a cópia, [b:132882bb9e][i:132882bb9e]acredito ser isso um bug[/i:132882bb9e][/b:132882bb9e].
Bem, já sabemos o que aconteceu.
Agora alguém pode me explicar por quê é assim ?
[color=red:132882bb9e][size=18:132882bb9e]ATÉ QUE ENFIM A SOLUÇÃO[/size:132882bb9e][/color:132882bb9e]
Antes de mais quero agradecer ao Massuda pela ajuda.
Bem, se vc´s se lembram do problema...eu tinha uma variável global que era uma estrutura e que não conseguia copiar seus dados para outras variáveis locais dentro das funções. Pois bem, agora já consigo e porquê ?
Quando declarei a variável [b:132882bb9e]TDB DB[/b:132882bb9e] fí-lo em [b:132882bb9e]db.h[/b:132882bb9e] e me causou todos esses transtornos, porém ao declará-la em [b:132882bb9e]db.c[/b:132882bb9e], tudo acabou por se acertar, ou seja, a variável global passou a ser copiável para outras variáveis locais, ou seja, a variável somente esta totalmente acessível quando declarada em [b:132882bb9e]db.c[/b:132882bb9e].
Quando ela estava declarada em db.h o processador aceitava a compilação mas não permitia a cópia, [b:132882bb9e][i:132882bb9e]acredito ser isso um bug[/i:132882bb9e][/b:132882bb9e].
Bem, já sabemos o que aconteceu.
Agora alguém pode me explicar por quê é assim ?
GOSTEI 0