Newsgroup: it.comp.lang.c++
Titolo: Problemi bizzarri...

Ciao a tutti,
visto che sono poco pratico (e molto imbranato) qualcuno riesce a
spiegarmi questi bizzarri comportamenti ?
Lo scopo del programma è il seguente: si collega ad un server remoto
(con il protocollo http), si autentica e scarica alcune pagine.
Quindo ho una funzione che calcola la base64 della login e password...
Il corpo del programma che prende i parametri passati alla funzione
main (quindi ip e log e pass).
Apro un flusso verso l'hd (fopen) e salvo le pagine scaricate.
Se provo i vari spezzoni funziona tutto regolarmente ... ma quando lo
metto tutto insieme iniziano i problemi.
1) la prima volta che compilo e lancio il 50% delle volte non si
collega al server (anche se sono sicuro che il server  è
raggiungibile)...
   quando si collega sembra funzionare bene
2) la seconda volta che lo lancio (anche ricompilando, ma lasciando la
finestra di dos aperta) mediamente mi mostra i primi output di
controllo e dopo si blocca... per una ventina di secondi e dopo si
ferma senza errori.
 Il blocco avviene quando incontra la funzione   pStream = fopen
("file.txt", "w");
3) Spesso e volentieri se non richiamo la funzione di conversione in
base64 sembra funzionare meglio nel senzo che 3 volte parte 7 no.
(sempre ricompilando e lasciando la finestra dos aperta).
la funzione base64 è su questo tipo
char* TraSform64 (char* Stringa)
La mia ipotesi è che ci sia qualche problema di gestione di
memoria .... AVETE QUALCHE IDEA ???
ps: il codice postato è di test... quindi se notate qualche cosa di
strano non vi preoccupate troppo
GRAZIE
#include <string.h>
#include <stdio.h>
#include <winsock.h>
#include <windows.h>
#define close closesocket
#define PORT 80
void addr_initialize (struct sockaddr_in *indirizzo, int port, long
IPaddr)
{
indirizzo->sin_family=AF_INET;
indirizzo->sin_port=htons((u_short)port);
indirizzo->sin_addr.s_addr=IPaddr;
}
char* TraSform64 (char* Stringa)
  {
  int ii,x,y;
  int NC=0;
  char *Ritorno;
  unsigned char c,d,p,r,a;
  Ritorno = (char*) malloc(120*sizeof(char));
  char valTrans[64] =
  { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' ,'J',
    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S' ,'T',
    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', '+', '/'};
  ii=0;
  r=0;
  p=0;
  x=2;
  Ritorno[120*sizeof(char)]='\0';
  while ((c=Stringa[ii++])!='\0')
   {
    d=c;
    p=d>>x;
    y=8-x;
    if (r==0)
     {
      r=d<<y;
      r=r>>2;
     }
    else
     {
      a=d>>x;
      p=r+a;
      r=d<<y;
      r=r>>2;
     }
    Ritorno[NC++]=valTrans[p];
    if (x==6)
     {
      a=d<<2;
      a=a>>2;
      Ritorno[NC++]=valTrans[a];
      r=0;
     }
    x=x+2;
    if (x==8)
     x=2;
   }
  if (x!=8)
   {
     Ritorno[NC++]=valTrans[r];
     Ritorno[NC++]='=';
     Ritorno[NC++]='\0';
   }
   return Ritorno;
 }
int main (int argc, char *argv[])
 {
  printf ("\n%d <....\n",argc);
  char *r;
  int sd;
  int i,nc,N,args;
  struct sockaddr_in server_addr;
  struct sockaddr_in mio_addr;
  char *buff;
  char *newline;
  char *coma[100];
  FILE *pStream;
  r=TraSform64("xxx");
  printf ("\n\nbase64=%s<->",r);
  printf ("\nip=%s<->\n",argv[1]);
  pStream = fopen("file.txt", "w");
  int mio_addr_len=sizeof(mio_addr);
  printf ("len mio addr %d\n\n",mio_addr_len);
  int error;
  #ifdef WIN32
   WSADATA wsaData;
   WSAStartup (0x0101,&wsaData);
  #endif
  addr_initialize (&server_addr, PORT, inet_addr(argv[1]));
  sd=socket(AF_INET, SOCK_STREAM, 0);
error=connect(sd, (struct sockaddr*)&server_addr, sizeof
(server_addr));
if (0==error)
{
 printf ("Ho eseguito la connessione %d \n",argc);
 getsockname(sd, (struct sockaddr*)&mio_addr, &mio_addr_len);
 printf ("La mia porta è: %d\n\n", ntohs(mio_addr.sin_port));
 printf ("********************++\n");
 nc=13;
 coma[1]="GET / HTTP/1.1\n";
 coma[2]="User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:
1.9.0.11) Gecko/2009060215 Firefox/3.0.11 (.NET CLR 3.5.30729)\n";
 coma[3]="Accept: text/html,application/xhtml+xml,application/
xml;q=0.9,*/*;q=0.8 \n";
 coma[4]="Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3 \n";
 coma[5]="Accept-Encoding: x-gzip, x-deflate, gzip, deflate, identity
\n";
 coma[6]="Accept-Charset: iso-8859-1, utf-8;q=0.5, *;q=0.5  \n";
 coma[7]="Keep-Alive: 300 \n";
 coma[8]="Connection: Keep-Alive \n";
 coma[9]="Host: 
10.10.10.10:80
 \n";
 coma[10]="Authorization: Basic uururururu \n";
 coma[11]="Credentials: log:pass \n";
 coma[12]="\n";
 coma[13]="\n";
 for (i=1; i<=nc; i++)
  {
   N=strlen(coma[i]);
   send (sd,coma[i],N,0);
   printf ("Stringa %s %d %d \n",coma[i],i,N);
  }
 i=0;
 N=1;
 buff = (char*) malloc(N*sizeof(char));
 buff[N*sizeof(char)]='\0';
 while (recv (sd,buff,N,0))
  {
   printf("%s",buff);
   fputs(buff,pStream);
   i++;
  }
}
else printf ("%s", "Errore di connect\n\n");
close(sd);
printf ("\n\n\n*************\n fclose (pStream);\n");
 fclose (pStream);
system("PAUSE");
return 0;
}

   Ritorno[120*sizeof(char)]='\0';
Qui stai scrivendo fuori dalla memoria allocata.
E.
PS: sizeof(char) � garantito essere sempre 1.

 PS: sizeof(char) è garantito essere sempre 1.
... per capire meglio:
Ritorno[120*sizeof(char)]='\0'; non significa che l'indirizzo memoria
a cui punta Ritorno più 120  (stessa dimensione allocata con malloc)
metti il carattere di fine stringa ?
Perchè mi dici che sto scrivendo fuori ?
Dovrei scrivere
Ritorno[119*sizeof(char)]='\0';
grazie

 
Non si tratta di essere pratici o imbranati, ma di leggersi un po' di
documentazione prima di scrivere codice.
Tanto per cominciare, 'send' e 'recv' restituiscono un valore di cui il
codice *deve* tenere conto. Vedi libro, man o tutorial per ulteriori
spiegazioni.
Poi, altri dettagli (come quello indicato da ?manu*, oppure l'assenza di
chiamate a free) suggeriscono che tu non abbia ancora chiari alcuni
principi del linguaggio C.
In terzo luogo, questo � il NG dedicato al C++. Anche le discussioni su API
POSIX o BSD (e.g. socket) sono OT.
E poi, perch� non usi una libreria per queste cose? libcurl, ad esempio. �
ben pi� istruttivo imparare ad usare una libreria, che cercare di
implementare protocolli a quel livello (senza nemmeno essersi letti le
specifiche, per altro).
Max
 

 Ritorno[119*sizeof(char)]='\0';
S�.
Max

 Max
Ok... il fatto di leggere la documentazione non risolve i problemi di
mancazo di pratica del linguaggio (o errori di distrazione) tipo
quello indicato da ?manu*...
... manuali consultati ... senza aver tirato risolto il problema !!!
Per quanto riguarda l'utilizzo di free nelle varie prove è stato usato
ma senza risultati utili (il problema rimaneva).
Poi per l'utilizzo delle librerie ... se dovessi concludere un
progetto in breve tempo o con scopi reali e/o pratici ti do raggione
ma se invece vuoi capire e conoscere un protocollo ...
... magari smanettarci non è una pessima idea...
Grazie comunque per la disponibilita

 Ritorno[119*sizeof(char)]='\0';
Nota anche che quel "sizeof(char)" � proprio concettualmente sbagliato. Se
Ritorno fosse un array di int, l'ultimo elemento sarebbe sempre
Ritorno[119], non Ritorno[119*sizeof(int)].
Max