Newsgroup: it.comp.lang.c
Titolo: problema con malloc

ho un problema. ho scritto questo programma per caricare delle immagini con formato proprietario da 12 bit.
se dichiaro le matrici staticamente funziona, se uso la malloc no. i valori dei dati della matrice sono da 2 Bytes quindi uso unsigned short e le dimensoni massime sono 1280x1024 pixels.
spero possiate dirmi dove commetto l'errore.
p.s. ho letto altri post su malloc e anche le faq (da cui ho tratto il pezzo di codice) ma comunque non funziona.
dando per scontato che le faq sono ok io mi sono bloccato su questo primo uso da parte mia della funzione malloc.
spero possiate aiutarmi.
ecco il programma (lunghetto ma saltate la parte di estrazione dati dal formato immagine).
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
void main() {
 unsigned short **b16data;
 unsigned short red[240][320]; 
 unsigned short blu[240][320]; 
 unsigned short r,c; /* generic row,column index */
 HWND hwnd = NULL;
 OPENFILENAME ofn;
 char szFileName[MAX_PATH] = "";
 ZeroMemory(&ofn, sizeof(ofn));
 ofn.lStructSize = sizeof(ofn);
 ofn.hwndOwner = hwnd;
 ofn.lpstrFilter = "12bit PCO (*.b16)\0*.b16\0All Files (*.*)\0*.*\0";
 ofn.lpstrFile = szFileName;
 ofn.nMaxFile = MAX_PATH;
 ofn.lpstrTitle = "Particle Image Velocimetry";
 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
 if(GetOpenFileName(&ofn)) {
  unsigned short i ;
  HANDLE hb1, hfr; 
  byte *charpointer; 
  byte *c1; 
  __int32 *b1; 
  DWORD z, zz; 
  int e; 
  long filesize; 
  long headerlength; 
  long imagewidth; 
  long imageheight; 
 
  hb1 = GlobalAlloc(GHND, 2000L); 
  charpointer = (byte *)GlobalLock(hb1); 
  hfr = CreateFile(ofn.lpstrFile, 
   GENERIC_READ, 
   0, 
   NULL, 
   OPEN_EXISTING, 
   FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 
   0); 
  if (hfr== INVALID_HANDLE_VALUE) { 
   GlobalUnlock(hb1); 
   GlobalFree(hb1); 
   printf("NO-FILE\n\a"); 
   while(!_kbhit());
  }
  e = ReadFile(hfr, (void *)charpointer, 400, &z, NULL); 
  if ((e == 0) || (z != 400)) { 
   CloseHandle(hfr); 
   GlobalUnlock(hb1); 
   GlobalFree(hb1); 
   printf("File-Read ERROR\n\a"); 
   while(!_kbhit());
  } 
  c1 = charpointer; 
  if ((*c1 != 'P') || (*(c1 + 1) != 'C') || (*(c1 + 2) != 'O') || (*(c1 + 3) != '-')) {
   CloseHandle(hfr); 
   GlobalUnlock(hb1); 
   GlobalFree(hb1); 
   printf("NO-PCO-FILE\n\a"); 
   while(!_kbhit());
  }
  // read FILEHEADER
  (__int32 *)b1 = (__int32 *)(charpointer + 4); // filesize
  filesize = *b1; 
  (__int32 *)b1 = (__int32 *)(charpointer + 8); // headerlength 
  headerlength = *b1; 
  z = filesize - headerlength; // BYTELENGTH 
  (__int32 *)b1 = (__int32 *)(charpointer + 12); // imagewidth 
  imagewidth = *b1; 
  (__int32 *)b1 = (__int32 *)(charpointer + 16); // imageheight 
  imageheight = *b1; 
  b16data = malloc ( imageheight * sizeof ( unsigned short * ) ) ;
  for ( i = 0 ; i < imageheight ; i++ )
   b16data[i] = malloc ( imagewidth * sizeof ( unsigned short ) ) ;
  if (IsBadWritePtr(b16data, z) != FALSE) printf("NO-MEMORY\n\a"); 
  // read DATA 12bit
  SetFilePointer(hfr, headerlength, NULL, FILE_BEGIN);
  e = ReadFile(hfr, (void *)b16data, z, &zz, NULL);
  if ((e == 0) || (z != zz)) {
   printf("NO-DATA\n\a"); 
   while(!_kbhit());
  }
  CloseHandle(hfr);
  GlobalUnlock(hb1);
  GlobalFree(hb1);
  printf("filesize: %d headerlength: %d bytelength: %d\n", filesize, headerlength, z); 
  printf("width: %d height: %d\n", imagewidth, imageheight); 
 }
// printf("data: %d\n", b16[9][9]);
}

 ha scritto nel messaggio
news:b8bmol$10t$1...@newsserver.cilea.it...
ho un problema. ho scritto questo programma per caricare delle immagini con
formato proprietario da 12 bit.
se dichiaro le matrici staticamente funziona, se uso la malloc no. i valori
dei dati della matrice sono da 2 Bytes quindi uso unsigned short e le
dimensoni massime sono 1280x1024 pixels.
spero possiate dirmi dove commetto l'errore.
Sbagli ad allocare la memoria: b16data è un puntatore a b16data[0] per cui
dovresti limitarti a:
b16data[0] = malloc ( imagewidth * sizeof ( unsigned short ) ) ;
b16data = &b16data[0];
  for ( i = 1 ; i < imageheight ; i++ )
   b16data[i] = malloc ( imagewidth * sizeof ( unsigned short ) ) ;
(penso che cmq sia un modo orribile di usare malloc questo.. parlo del mio
codice improvvisato :)
Non ho letto tutto il codice, non ho buona padronanza del malloc, ma penso
sia almeno concettualmente corretto. Mi scuso con tutti se sto dicendo
eventuali czzate :P
    Fab

codice improvvisato :)
Mi sono perso il messaggio iniziale, pero' questo codice mi
sembra decisamente errato. Io scriverei qualcosa come:
   unsigned short **b16data;
   ...
   b16data = malloc( imageheight * sizeof( unsigned short * ) );
   for (i=0; i<imageheight; i++)
     b16data[i] = malloc( imagewidth * sizeof( unsigned short ) );
   ...
 
   for (i=0; i<imageheight; i++)
     free( b16data[i] );
   free( b16data );
Se le immagini da allocare fossero molte allora invece di fare
una malloc per i puntatori di riga piu' una malloc per ogni
riga si potrebbero fare solo due malloc in totale...
   b16data = malloc( imageheight * sizeof( unsigned short * ) );
   b16data = malloc( imagewidth * imageheight 
                     * sizeof( unsigned short *) );
   for (i=1; i<imageheight; i++)
     b16data[i] = b15data[i-1] + imagewidth;
   ...
   free( b16data[0] );
   free( b16data );
HTH
Andrea

innanzitutto grazie per l'aiuto. ho fatto ordine nel codice e provato a seguire i vostri consigli ma comunque non funziona.
e mannaggia non capisco perché! aiuto!
ecco la versione leggibile del programma:
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
typedef struct {
 unsigned short width, height; 
 unsigned short **matrix;
} MATRIX;
void malloc_matrix (MATRIX *pointer, unsigned short row, unsigned short column) {
 unsigned short i;
 pointer->width = column;
 pointer->height = row;
 pointer->matrix = malloc(row * sizeof(unsigned short *));
 for (i = 0; i < row; i++)
  pointer->matrix[i] = malloc(column * sizeof(unsigned short));
}
void free_matrix (MATRIX *pointer) {
 unsigned short i;
 for (i = 0; i < pointer->height; i++)
  free(pointer->matrix[i]);
 free(pointer->matrix);
}
MATRIX b16data; 
void main(void) {
 extern void b16file(); 
 extern void dcc();
 unsigned short red[240][320]; 
 unsigned short blu[240][320]; 
 unsigned short r,c; /* generic row,column index */
 
 HWND hwnd = NULL;
 OPENFILENAME ofn;
 char szFileName[MAX_PATH] = "";
 ZeroMemory(&ofn, sizeof(ofn));
 ofn.lStructSize = sizeof(ofn);
 ofn.hwndOwner = hwnd;
 ofn.lpstrFilter = "12bit PCO (*.b16)\0*.b16\0All Files (*.*)\0*.*\0";
 ofn.lpstrFile = szFileName;
 ofn.nMaxFile = MAX_PATH;
 ofn.lpstrTitle = "Particle Image Velocimetry";
 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
 if(GetOpenFileName(&ofn)) { 
  malloc_matrix(&b16data, 480, 640);
  b16file(ofn.lpstrFile, b16data);
 }
 free_matrix(&b16data);
}
e il file che serve per leggere l'immagine a 12 bit (questo funziona staticamente, lo aggiungo perché potrebbe essere utile a capire le dimensioni delle matrici da minipolare...)
#include <conio.h>
#include <stdio.h> 
#include <windows.h> 
void b16file(char *filename, void *buffer) {
 HANDLE hb1, hfr; 
 byte *charpointer; 
 byte *c1; 
 __int32 *b1; 
 DWORD z, zz; 
 int e; 
 long filesize; 
 long headerlength; 
 unsigned short imagewidth; 
 unsigned short imageheight; 
 hb1 = GlobalAlloc(GHND, 2000L); 
 charpointer = (byte *)GlobalLock(hb1); 
 hfr = CreateFile(filename, 
  GENERIC_READ, 
  0, 
  NULL, 
  OPEN_EXISTING, 
  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 
  0); 
 if (hfr== INVALID_HANDLE_VALUE) { 
  GlobalUnlock(hb1); 
  GlobalFree(hb1); 
  printf("NO-FILE\n\a"); 
  while(!_kbhit());
  exit(0); 
 }
 e = ReadFile(hfr, (void *)charpointer, 400, &z, NULL); 
 if ((e == 0) || (z != 400)) { 
  CloseHandle(hfr); 
  GlobalUnlock(hb1); 
  GlobalFree(hb1); 
  printf("File-Read ERROR\n\a"); 
  while(!_kbhit());
 } 
 c1 = charpointer; 
 if ((*c1 != 'P') || (*(c1 + 1) != 'C') || (*(c1 + 2) != 'O') || (*(c1 + 3) != '-')) {
  CloseHandle(hfr); 
  GlobalUnlock(hb1); 
  GlobalFree(hb1); 
  printf("NO-PCO-FILE\n\a"); 
  while(!_kbhit());
 }
 // read FILEHEADER
 (__int32 *)b1 = (__int32 *)(charpointer + 4); // filesize
 filesize = *b1; 
 (__int32 *)b1 = (__int32 *)(charpointer + 8); // headerlength 
 headerlength = *b1; 
 z = filesize - headerlength; // BYTELENGTH 
 (__int32 *)b1 = (__int32 *)(charpointer + 12); // imagewidth 
 imagewidth = *b1; 
 (__int32 *)b1 = (__int32 *)(charpointer + 16); // imageheight 
 imageheight = *b1; 
 if (IsBadWritePtr(buffer, z) != FALSE) printf("NO-MEMORY\n\a"); 
 // read DATA 12bit
 SetFilePointer(hfr, headerlength, NULL, FILE_BEGIN);
 e = ReadFile(hfr, (void *)buffer, z, &zz, NULL);
 if ((e == 0) || (z != zz)) {
  printf("NO-DATA\n\a"); 
  while(!_kbhit());
 }
 CloseHandle(hfr);
 GlobalUnlock(hb1);
 GlobalFree(hb1);
}
grazie

 sembra decisamente errato. Io scriverei qualcosa come:
non so proprio sotto che effetto posso aver scritto certe cose.. scusatemi!!
Fab :P

 e = ReadFile(hfr, (void *)buffer, z, &zz, NULL);
e oltrettutto ci scrive dentro il contenuto del file
trattandolo come dice il parametro come un "buffer"
destrutturato... un semplice ammasso di byte (e la
cosa e' anche un po' curiosa, perche' nessuno ha detto
alla funzione quanto il buffer e' grosso e il chiamante
non ha modo di allocarlo correttamente).
Strano che tu sia riuscito a compilare questa roba...
un compilatore schizzinoso si sarebbe secondo me
dovuto arrabbiare vedendo prima un prototype "alla cieca"
(che io gia' segnalerei con un warning), poi una chiamata
con dei parametri e infine una definizione con altri
parametri (e qui darei un errore).
La cosa veramente incredibile di questo programma
e' che si sono usate "finezze" non portabili come
un dialog per la richiesta del nome file e chiamate
non standard per la lettura del file stesso, pero'
l'algoritmo di base e' totalmente errato per molte
ragioni. Voglio sperare che si tratti di roba che
hai copiato qua e la' ... perche' altrimenti il
livello di confusione che devi avere in testa e'
veramente pazzesco. Proprio non hai tempo di
imparare prima un po' di C ?
Scusa se questo post ti sembra duro, ma tu proprio
il C non lo sai, e prima te ne rendi conto e meglio
e' (perche' prima potrai metterti di buzzo buono a
studiarlo). Se invece e' un problema contingente e
immediato come farti firmare uno statino in cui e'
attestato che il C lo conosci (ovvero il falso)
allora proprio non ho tempo e voglia di darti retta.
Andrea

 Andrea
ok, non lo so il c. e mi metto di buzzo buono a studiarlo.
non va bene provare a scrivere un programma e debuggarselo fino trovarne tutti gli errori?
e se non ci riesci chiedere aiuto ad un libro, i vecchi post, le faq e il ng?
e poi se sono uno zuccone e chiedo 2 volte le cose tu ti incazzi?

scusate, ho riletto ora il post e mi sono accorto di aver scritto di fretta e digitato un sacco di refusi nelle parole.
ero agitato...
ciao

2 volte le cose tu ti incazzi?
Mi scuso ancora... per penitenza quasi quasi ti scrivo
una mia versione. Non sono riuscito a trovare in internet
dei file PCO con cui provare... quindi ne ho creato uno
"a mano" da quello che ho capito del codice...
So che ora il tuo programma funziona... comunque magari
puo' esserti utile un diverso punto di vista...
Il programma non l'ho scritto completamente portabile
(in particolare la dimensione degli interi e il
problema dell bigendian o smallendian e' stato ignorato)
per non aumentare il fumo. Non sono comunque cose
complicate da aggiungere se tu dovessi portare il codice
su un altro tipo di computer.
HTH
Andrea
----------------
#include <stdio.h>
#include <stdlib.h>
/****************
**              **
**   Utilita'   **
**              **
 ****************/
void die(const char *why)
{
  puts(why);  /* Spiega il motivo */
  exit(1);    /* Chiude brutalmente */
}
void *my_malloc(int size)
{
  void *p = malloc(size);
  if (p==NULL) die("Memoria insufficiente.");
  return p;
}
void my_free(void *p)
{
  free(p);
}
/***************
**             **
**   Matrix    **
**             **
 ***************/
typedef struct T_MATRIX
{
  int width, height; 
  unsigned short **data;
} Matrix;
Matrix *new_matrix(int width,int height)
{
  int y;
  Matrix *m = my_malloc(sizeof(Matrix));
  m->width = width;
  m->height = height;
  m->data = my_malloc(height * sizeof(unsigned short *));
  for (y=0; y<height; y++)
    m->data[y] = my_malloc(width * sizeof(unsigned short));
  return m;
}
void free_matrix(Matrix *m)
{
  int y;
  for (y=0; y<m->height; y++)
    my_free(m->data[y]);
  my_free(m->data);
  my_free(m);
}
/***************
**             **
**   B16File   **
**             **
 ***************/
Matrix *load_b16file(const char *filename)
{
  Matrix *m;
  int filesize,headerlenght,width,height;
  int y;
  FILE *f = fopen(filename,"rb");
  if (f==NULL) return NULL;
  if (
      fgetc(f)!='P' ||
      fgetc(f)!='C' ||
      fgetc(f)!='O' ||
      fgetc(f)!='-' ||
 
      fread(&filesize,1,4,f)!=4     ||
      fread(&headerlenght,1,4,f)!=4 ||
      fread(&width,1,4,f)!=4        ||
      fread(&height,1,4,f)!=4       ||
 
      width<0 || width>10000        ||
      height<0 || height>10000      ||
      filesize<0 || headerlenght<0  ||
      width*height*2 + headerlenght != filesize
     )
  {
    /* Formato errato */
    fclose(f);
    return NULL;
  }
 
  /* Alloca la matrice e legge il contenuto */
  m = new_matrix(width,height);
  fseek(f,headerlenght,SEEK_SET);
  for (y=0; y<height; y++)
    if ((int)fread(m->data[y],2,width,f)!=width)
    {
      /* Lettura non completa */
      fclose(f);
      free_matrix(m);
      return NULL;
    }
  fclose(f);
  return m;
}
/************
**          **
**   Main   **
**          **
 ************/
int main(int argc,char *argv[])
{
  int i;
  if (argc<2)
    die("Mancano i nomi dei file da elaborare");
 
  for (i=1; i<argc; i++)
  {
    Matrix *m = load_b16file(argv[i]);
    if (m==NULL)
    {
      printf("*** Errore in caricamento '%s'\n",
             argv[i]);
    }
    else
    {
      printf("File '%s' -> %ix%i pixel\n",
             argv[i],m->width,m->height);
      /* ... elaborazione ... */
      free_matrix(m);
    }
  }
  return 0;
}

non voglio aggiungere altro se non grazie per il tuo esempio che stasera mi studio ben bene.
sono molto felice che tu abbia capito il mio approccio.
ma mi ha fatto piacere soprattutto una critica dura. mi hai insegnato comunque molte cose.
e tanto per dirne una semplice semplice, la routine di open file con le api di win la metto in un sorgente separato così il main non è più contaminato ;-)
per il resto devo apettare stasera.
ciao andrea e grazie.
maurizio
p.s. ci ritrovere nel ng... ho troppo da imapare.
ma mi cerco nelle faq un libro sul c serio.


Senza voler scatenare flame inutili, ma usare qualcosa di piu' specifico
per il calcolo?
Tipo:
a) Octave
b) Scilab
c) Matlab
d) Fortran90 
Io ho scoperto da posco il fortran90 e mi trovo veramente bene.