Newsgroup: it.comp.lang.c
Titolo: Aiutatemi :"La memoria non poteva essere written"-non capisco

Mi trovo a dovere scrivere dei programmi per calcolo numerico (la materia
che sto preparando) e mi sono bloccato sul metodo di Jacobi per la
risoluzione di sistemi con metodo iterativo.
Non riesco proprio a capire cosa non va nel mio codice.
L' algoritmo è preso dal libro della prof.
Credo che il problema sia nella gestione dinamica della memoria perchè ad un
certo punto mi dice per ben tre volte che la memoria non poteva essere
"written".
Anche se capisco la scocciatura di dovere leggere il codice scritto da un
altro ve lo posto lo stesso nella speranza che qualche anima pia mi possa
aiutare ad individuare l' errore.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
float norma_matrice(float **matri);
char rispo;
int i,j,k,n,iter;
float eps,vnorm,vv;
float **matrice;
float *x;
float *y;
main()
{
   printf("----------------------------------------------------\n");
 printf("---------------Programma Jacobi---------------------\n");
   printf("----------------------------------------------------\n");
   printf("\nInserisci l'ordine del sistema :");
   scanf("%d",&n);
   matrice=(float **)malloc(n*sizeof(float *));
   for(i=1;i<=n;i++) matrice[i]=(float *)malloc((n+1)*sizeof(float));
   printf("Introduci gli elementi della matrice:");
   for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
       {
          printf("\n(%d,%d)=",i,j);
            scanf("%e",&matrice[i][j]);
         }
   printf("Introduci i termini noti:");
   for(i=1;i<=n;i++)
         {
          printf("\nb(%d)=",i);
            scanf("%e",&matrice[i][n+1]);
         }
   /*Verifica elementi nulli diagonali*/
   for(i=1;i<=n;i++)
    if(matrice[i][i]==0)
       {
          printf("\nHo trovato un elemento diagonale nullo");
            getchar();
            getchar();
            exit(0);
         }
   for(i=1;i<=n;i++)
    {
       for(j=1;j<=n;j++) if(i!=j)
matrice[i][j]=-matrice[i][j]/matrice[i][i];
         matrice[i][n+1]=matrice[i][n+1]/matrice[i][i];
         matrice[i][i]=0;
      }
   if(norma_matrice(matrice)>1)
    {
       printf("\nLe norme verificate sono >1");
         printf("\nVuoi provare a continuare ?");
         scanf("%c",&rispo);
         scanf("%c",&rispo); /*La devo aggiungere perchè saltrimenti non si
ferma*/
         if(rispo=='n') exit(0);
      }
   printf("\nIntroduci il numero massimo di iterazioni:");
   scanf("%d",&iter);
   printf("\nIntroduci lo zero di calcolo:");
   scanf("%e",&eps);
   /*Allocazione dinamica vettori*/
   x=(float *)malloc(n*sizeof(float));
   y=(float *)malloc(n*sizeof(float));
   /*Calcolo della soluzione con metodo Iterativo di Jacobi*/
   for(i=1;i<=n;i++) x[i]=matrice[i][n+1];
   k=0;
   do
    {
       k=k+1;
         vnorm=0;
         for(i=1;i<=n;i++)
          {
             y[i]=matrice[i][n+1];
               for(j=1;j<=n;j++) y[i]=y[i]+matrice[i][j]*x[j];
               vv=abs(y[i]-x[i]);
               if(vv>vnorm) vnorm=vv;
            }
         for(i=1;i<=n;i++) x[i]=y[i];
      }
   while((k!=iter)||(vnorm>eps));
   printf("\nNumero di iterazioni :%d",k);
   printf("\nIl vettore soluzione e' :");
   for(i=1;i<=n;i++) printf("x(%d)=%e",i,x[i]);
   return(1);
}
float norma_matrice(float **matri)
 {
    int i,j;
    float s,nor;
      nor=0;
      for(i=1;i<=n;i++)
       {
          s=0;
            for(j=1;j<=n;j++) s=s+abs(matri[i][j]);
            if(s>nor) nor=s;
         }
      if(nor>1)
       {
            printf("\nLa norma infinito non ha dato un risultato < 1.Tento
con la norma 1");
          nor=0;
            for(i=1;i<=n;i++)
             {
                s=0;
                  for(j=1;j<=n;j++) s=s+abs(matri[j][i]);
                  if(s>nor) nor=s;
               }
         }
      return(nor);
   }
Se avete consigli,suggerimenti,critiche accetto tutto, però per favore
aiutatemi.

    for(i=1;i<=n;i++) matrice[i]=(float *)malloc((n+1)*sizeof(float));
qui sopra c'e' gia' un errore gravissimo che sicuramente puo'
impedire il funzionamento. Allochi per matrice
n puntatori, ma poi nel ciclo sotto fai andare l'indice da 1 a n
e quindi con matrice[n] accedi all'elemento (n+1)-esimo della
matrice, che non esiste!
In generale in C sarebbe meglio usare sempre indici che partono
da 0.
Non ho guardato il resto del programma.
ciao,
e.

Ho effettuato le modifiche che mi ha consigliato Caro Estintore , ma il
problema permane

Scusa perchč dichiari matrice come puntatore a puntatore di float?
Non puoi dichiararla semplicemente cosě?
float *matrice=0;
matrice=malloc(n*n*sizeof(float));
In questo modo hai allocato lo spazio per una matrice quadrata di 
dimensione n*n*sizof(float) bytes, cioč un array che va da 0 a n*n-1.
Ovviamente se vuoi accedere all'elemento (r,c), con:
r = riga, 1<=r<=n;
c = colonna, 1<=c<=n;
devi fare:
matrice[n*r+c-1]
E comunque dopo ogni chiamata a malloc ti conviene controllare che la 
memoria sia stata effettivamente allocata:
float *matrice=0;
...
matrice=malloc(n*n*sizeof(float));
if (matrice)
{
   ...
   free(matrice);
   matrice=0;
};
else
   printf("Impossibile allocare la memoria...\n");
-- 
Quando noi ignoranti eravamo di piů, tutto era piů bello (A. Celentano).
  ___   _   ___ _  _______   _______ ___
|   \ /_\ | _ \ |/ / _ ) \ / /_   _| __|
| |) / _ \|   / ' <| _ \\ V /  | | | _|
|___/_/ \_\_|_\_|\_\___/ |_|   |_| |___|

 problema permane
cioe' hai modificato anche la allocazione dopo,
mettendo (n+2) dove avevi messo (n+1) ?
(ho notato ora che memorizzi il termine noto dopo la
matrice)
e anche le allocazioni dei vettori che erano
sbagliate per lo stesso motivo?
Comunque e' un programma piccolissimo:
o impari ad usare un debugger (tipo ddd sotto
linux) o ci metti 2 stampe e trovi dove
ti da esattamente l'errore.
Se poi prosegui in queste cose e le vuoi
fare seriamente ti consiglio di cambiare
tutti i float in double.
Fare calcoli numerici con i float,
a meno che tu non debba memorizzare
milioni e milioni di valori non conviene:
il risparmio in termini di velocita'
e' piccolo, mentre il pericolo
che l'errore faccia brutti scherzi aumenta molto.
ciao,
e.

 tutti i float in double.
Inizialmente quando avevo cominciato a scrivere programmi per questo corso
usavo i double , ma non riuscendo a capire il perchè i risultati delle prove
che effettuavo erano sbagliati  sono passato ai float.
Colgo l' occasione per chiederti se mi sai dare una spiegazione su questo .
Grazie tantissimo delle tue risposte e scusami se mi sono dilungato

Ho rieffetuuato le modifiche che mi hai consigliato :
Ho sostituito i float con i double, ho modificato gli indici dei cicli for e
ho ricompilato.
Tuttavia mi da ancora errore , diverso ma pur sempre errore :
per tre volte si presenta una finestra con la seguente dicitura :
exception unknown software exception (.....) nell' applicazione alla
posizione (............)
Qualche idea?

 Colgo l' occasione per chiederti se mi sai dare una spiegazione su questo .
Se le cose cambiano passando da float a double io mi fermerei subito
perche' c'e' qualcosa di inerentemente errato: come fai a fidarti di un 
programma che cambiando tipo di dato si pianta oppure no ?
Ci sono 2 possibilita' principali.
1) che stai sbagliando ad usare le funzioni di input
come scanf() che vuole due sintassi diverse per leggere double (%lf) e
float (%f). Se sbagli sintassi leggi delle cose prive di senso.
Diversa e' invece la faccenda con la printf() perche' in quel caso
devi usare %f sia per i double sia per i float (che verranno convertiti
automaticamente in double dalla printf)
2) Hai scavolato con le allocazioni di memoria. Siccome i double 
occupano tipicamente il doppio di memoria e' piu' facile che un
errore di allocazione (e quindi di accesso) venga rivelato usando
i double piuttosto che i float.
ciao,
g.

 Colgo l' occasione per chiederti se mi sai dare una spiegazione su questo
.
bisognerebbe capire cosa intendi per risultati 'sbagliati'. Un esempio di un
calcolo sbagliato?
Ciao,
Ema

Ho trovato l' errore :evivva!!!!!!!!!!!!!!!!!!!!!!!!!!!
Il problema dopo la correzione dell' allocazione di  memoria  era nel ciclo
do-while finale.
In pratica doveva essere
do
    {
        bla,bla....
    }
while((k!=iter)||(vnorm>eps));
e vostre indicazioni mi sono state molto utili.
Qundi grazie a tutti per le risposte.
Sono molto interessato alle funzioni di debugging attraverso il software :
se c'è qualcuno che mi può dare delle indicazioni più precise gli sarò molto
grato.
In questo momento , come ho detto,  sto usando il borland c++ builder 5.0
ma se mi consigliate un altro compilatore con funzioni di debugging per il c
più potente cercherò di scaricarlo e testarlo.
Vorrei inoltre sapere se siete sicuri che per leggere i double con scanf si
debba usare %lf .
Io usavo %e.
Infine vorrei aggiungere : avete idea di come posso creare una libreria che
condenga le funzioni che vado via via creando in modo da includerla nel file
all'inizio?
Mi hanno detto che esiste un metodo automatico, ne sapete niente?
Grazie

 Io usavo %e.
Questo e' il manuale sotto linux, ma dovrebbe essere piu' o meno
uguale sotto il borland. Comunque queste informazioni le potevi
trovare agevolmente in rete.
Leggendo con attenzione si deduce che %e e %f sono uguali
e servono per legger i float, mentre %le e %lf sono uguali
e servono per leggere i double.
ciao,
g.
NAME
        scanf,  fscanf,  sscanf - input format conversion
SYNOPSIS
        #include <stdio.h>
        int scanf( const char *format, ...);
        int fscanf( FILE *stream, const char *format, ...);
        int sscanf( const char *str, const char *format, ...);
DESCRIPTION
        The scanf family of functions scans input according  to  a
        format  as  described below.  This format may contain con­
        version specifiers; the results from such conversions,  if
        any,  are stored through the pointer arguments.  The scanf
        function reads input from the standard input stream stdin,
        fscanf  reads  input  from  the stream pointer stream, and
        sscanf reads its input from the character  string  pointed
        to by str.
        Each  successive pointer argument must correspond properly
        with each successive conversion specifier (but  see  `sup­
        pression' below).  All conversions are introduced by the %
        (percent sign) character.  The format string may also con­
        tain other characters.  White space (such as blanks, tabs,
        or newlines) in the format  string  match  any  amount  of
        white  space,  including  none,  in the input.  Everything
        else matches only itself.  Scanning stops  when  an  input
        character  does  not match such a format character.  Scan­
        ning also stops when an input conversion  cannot  be  made
        (see below).
CONVERSIONS
        Following  the  % character introducing a conversion there
        may be a number of flag characters, as follows:
        *      Suppresses assignment.  The conversion that follows
               occurs as usual, but no pointer is used; the result
               of the conversion is simply discarded.
        a      Indicates that the conversion will be s, the needed
               memory  space for the string will be malloc'ed  and
               the pointer to it will  be  assigned  to  the  char
               pointer  variable,  which  does not have to be ini­
               tialised before.  This flag does not exist in  ANSI
               C.
        h      Indicates  that the conversion will be one of dioux
               or n and the next pointer is a pointer to  a  short
               int (rather than int).
        l      Indicates either that the conversion will be one of
               dioux or n and the next pointer is a pointer  to  a
               long  int (rather than int), or that the conversion
               will be one of  efg  and  the  next  pointer  is  a
               pointer  to double (rather than float).  Specifying
               two l flags is equivalent to the L flag.
        L      Indicates that the conversion will  be  either  efg
               and the next pointer is a pointer to long double or
               the conversion will be dioux and the  next  pointer
               is a pointer to long long.  (Note that long long is
               not an ANSI C type. Any program using this will not
               be portable to all architectures).
        q      equivalent  to L.  This flag does not exist in ANSI
               C.
        In addition to these flags, there may be an optional maxi­
        mum  field  width, expressed as a decimal integer, between
        the % and the conversion.  If no width is given, a default
        of  `infinity' is used (with one exception, below); other­
        wise at most this many characters are scanned in  process­
        ing  the  conversion.  Before conversion begins, most con­
        versions skip white space; this white space is not counted
        against the field width.
        The following conversions are available:
        %      Matches a literal `%'.  That is, `%%' in the format
               string matches a single input  `%'  character.   No
               conversion  is done, and assignment does not occur.
        d      Matches an optionally signed decimal  integer;  the
               next pointer must be a pointer to int.
        D      Equivalent  to  ld;  this exists only for backwards
               compatibility.  (Note: thus only in libc4. In libc5
               and  glibc  the %D is silently ignored, causing old
               programs to fail mysteriously.)
        i      Matches an  optionally  signed  integer;  the  next
               pointer  must  be a pointer to int.  The integer is
               read in base 16 if it begins with `0x' or `0X',  in
               base 8 if it begins with `0', and in base 10 other­
               wise.  Only characters that correspond to the  base
               are used.
        o      Matches an unsigned octal integer; the next pointer
               must be a pointer to unsigned int.
        u      Matches  an  unsigned  decimal  integer;  the  next
               pointer must be a pointer to unsigned int.
        x      Matches  an  unsigned hexadecimal integer; the next
               pointer must be a pointer to unsigned int.
        X      Equivalent to x
        f      Matches an optionally signed floating-point number;
               the next pointer must be a pointer to float.
        e      Equivalent to f.
        g      Equivalent to f.
        E      Equivalent to f
        s      Matches  a  sequence of non-white-space characters;
               the next pointer must be a pointer to char, and the
               array  must  be  large  enough  to  accept  all the
               sequence and the terminating  NUL  character.   The
               input string stops at white space or at the maximum
               field width, whichever occurs first.
        c      Matches  a  sequence  of  width  count   characters
               (default  1); the next pointer must be a pointer to
               char, and there must be enough  room  for  all  the
               characters  (no  terminating  NUL  is  added).  The
               usual skip of leading white  space  is  suppressed.
               To skip white space first, use an explicit space in
               the format.
        [      Matches a nonempty sequence of characters from  the
               specified  set  of  accepted  characters;  the next
               pointer must be a pointer to char, and  there  must
               be  enough  room  for  all  the  characters  in the
               string, plus  a  terminating  NUL  character.   The
               usual  skip  of  leading white space is suppressed.
               The string is to be made up of  characters  in  (or
               not in) a particular set; the set is defined by the
               characters between the open bracket [ character and
               a  close  bracket  ]  character.   The set excludes
               those characters if the first character  after  the
               open bracket is a circumflex ^.  To include a close
               bracket in the set, make  it  the  first  character
               after the open bracket or the circumflex; any other
               position will end the set.  The hyphen character  -
               is  also  special;  when  placed  between two other
               characters, it adds all intervening  characters  to
               the  set.   To  include  a hyphen, make it the last
               character before  the  final  close  bracket.   For
               instance,  `[^]0-9-]'  means  the  set  `everything
               except  close  bracket,  zero  through  nine,   and
               hyphen'.   The string ends with the appearance of a
               character not in the (or, with  a  circumflex,  in)
               set or when the field width runs out.
        p      Matches  a  pointer  value  (as  printed by `%p' in
               printf(3); the next pointer must be  a  pointer  to
               void.
        n      Nothing is expected; instead, the number of charac­
               ters consumed thus far from  the  input  is  stored
               through  the  next pointer, which must be a pointer
               to int.  This is not a conversion, although it  can
               be  suppressed  with  the  *  flag.  The C standard
               says: `Execution of a %n directive does not  incre­
               ment  the  assignment count returned at the comple­
               tion of execution' but  the  Corrigendum  seems  to
               contradict  this.  Probably  it is wise not to make
               any assumptions on the effect of %n conversions  on
               the return value.
RETURN VALUE
        These functions return the number of input items assigned,
        which can be fewer than provided for, or even zero, in the
        event  of  a matching failure.  Zero indicates that, while
        there was input available, no conversions  were  assigned;
        typically  this is due to an invalid input character, such
        as an alphabetic character for  a  `%d'  conversion.   The
        value  EOF  is  returned if an input failure occurs before
        any conversion such as an end-of-file occurs. If an  error
        or end-of-file occurs after conversion has begun, the num­
        ber of conversions which were  successfully  completed  is
        returned.