0

I am new to compiling in linux environment. Anyway, I have a source code in C which is suppose to read a sequence of .pgm image files, compress them and write the compressed file to a new .pgm file. However, when I compile I get the following error message

*** glibc detected *** ./a.out: free(): invalid pointer: 0x00007fefc6176010 ***  
======= Backtrace: =========  
/lib/x86_64-linux-gnu/libc.so.6(+0x7a6e6)[0x7fefda73b6e6]  
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x6c)[0x7fefda73f9cc]  
./a.out[0x408491]  
./a.out[0x408565]  
./a.out[0x401048]  
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fefda6e230d]  
./a.out[0x400a59]  
======= Memory map: ========    
00400000-0040b000 r-xp 00000000 07:00 299109                             /home/skyjuice/PROJECT3/a.out  
0060a000-0060b000 r--p 0000a000 07:00 299109                             /home/skyjuice/PROJECT3/a.out  
0060b000-0060c000 rw-p 0000b000 07:00 299109                             /home/skyjuice/PROJECT3/a.out  
0060c000-059f8000 rw-p 00000000 00:00 0   
05ebb000-05ee3000 rw-p 00000000 00:00 0                                  [heap]  
7fefc0000000-7fefc0021000 rw-p 00000000 00:00 0   
7fefc0021000-7fefc4000000 ---p 00000000 00:00 0   
7fefc59d3000-7fefc59d4000 rw-p 00000000 00:00 0   
7fefc5f60000-7fefc5f75000 r-xp 00000000 07:00 2117                       /lib/x86_64-linux-gnu/libgcc_s.so.1
7fefc5f75000-7fefc6174000 ---p 00015000 07:00 2117                       /lib/x86_64-linux-gnu/libgcc_s.so.1
7fefc6174000-7fefc6175000 r--p 00014000 07:00 2117                       /lib/x86_64-linux-gnu/libgcc_s.so.1
7fefc6175000-7fefc6176000 rw-p 00015000 07:00 2117                       /lib/x86_64-linux-gnu/libgcc_s.so.1  
7fefc6176000-7fefda6c1000 rw-p 00000000 00:00 0   
7fefda6c1000-7fefda858000 r-xp 00000000 07:00 904195                     /lib/x86_64-linux-gnu/libc-2.13.so  
7fefda858000-7fefdaa57000 ---p 00197000 07:00 904195                     /lib/x86_64-linux-gnu/libc-2.13.so  
7fefdaa57000-7fefdaa5b000 r--p 00196000 07:00 904195                     /lib/x86_64-linux-gnu/libc-2.13.so  
7fefdaa5b000-7fefdaa5c000 rw-p 0019a000 07:00 904195                     /lib/x86_64-linux-gnu/libc-2.13.so  
7fefdaa5c000-7fefdaa62000 rw-p 00000000 00:00 0   
7fefdaa62000-7fefdaae5000 r-xp 00000000 07:00 904199                     /lib/x86_64-linux-gnu/libm-2.13.so  
7fefdaae5000-7fefdace4000 ---p 00083000 07:00 904199                     /lib/x86_64-linux-gnu/libm-2.13.so  
7fefdace4000-7fefdace5000 r--p 00082000 07:00 904199                     /lib/x86_64-linux-gnu/libm-2.13.so  
7fefdace5000-7fefdace6000 rw-p 00083000 07:00 904199                     /lib/x86_64-linux-gnu/libm-2.13.so  
7fefdace6000-7fefdad07000 r-xp 00000000 07:00 644102                     /lib/x86_64-linux-gnu/ld-2.13.so  
7fefdaeeb000-7fefdaeee000 rw-p 00000000 00:00 0   
7fefdaf04000-7fefdaf06000 rw-p 00000000 00:00 0   
7fefdaf06000-7fefdaf07000 r--p 00020000 07:00 644102                     /lib/x86_64-linux-gnu/ld-2.13.so  
7fefdaf07000-7fefdaf09000 rw-p 00021000 07:00 644102                     /lib/x86_64-linux-gnu/ld-2.13.so  
7fff1b020000-7fff1b0ca000 rw-p 00000000 00:00 0                          [stack]  
7fff1b148000-7fff1b149000 r-xp 00000000 00:00 0                          [vdso]  
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]  
Aborted

Below is a snippet of the source code

#define START_FRAME 141 #define END_FRAME 143 #define SKIP_FRAME 1 #define INPUT_STRING "/home/image%03d.pgm"

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

  unsigned char *frm1, *frm2, *predict, *predictDb, *frm1E;    
  unsigned char *rcnDiff, *diff, *rcnFrm1, *rcnFrm2, *wave;  
  int           *xVct, *yVct, *pxE, *pyE, *code;  
  int   nx  = 1920, ny = 1080, nxy;  
  int   bSize  = 16, nbx, nby, nbxy;
  int   frameNo = START_FRAME;  
  int   nxy  = nx * ny;

  frm1       = (unsigned char *) malloc(sizeof(unsigned char) * nxy);  
  frm2       = (unsigned char *) malloc(sizeof(unsigned char) * nxy);  
  rcnFrm1    = (unsigned char *) malloc(sizeof(unsigned char) * nxy);  
  rcnFrm2    = (unsigned char *) malloc(sizeof(unsigned char) * nxy);  
  predict    = (unsigned char *) malloc(sizeof(unsigned char) * nxy);  
  predictDb  = (unsigned char *) malloc(sizeof(unsigned char) * nxy);  
  diff       = (unsigned char *) malloc(sizeof(unsigned char) * nxy);  
  rcnDiff    = (unsigned char *) malloc(sizeof(unsigned char) * nxy);  
  wave       = (unsigned char *) malloc(sizeof(unsigned char) * nxy);    
  xVct       = (int *) malloc(sizeof(int) * nbxy);  
  yVct       = (int *) malloc(sizeof(int) * nbxy);  

  code       = (int *) malloc(sizeof(int) * tgtBits1);    
  frm1d      = (double *) malloc(sizeof(double) * nxy);  
  frm2d      = (double *) malloc(sizeof(double) * nxy);  
  predictd   = (double *) malloc(sizeof(double) * nxy);  
  predictDbd = (double *) malloc(sizeof(double) * nxy);  
  rcnFrm1d   = (double *) malloc(sizeof(double) * nxy);  
  rcnFrm2d   = (double *) malloc(sizeof(double) * nxy);  
  wavFrm1    = (double *) malloc(sizeof(double) * nxy);  
  wavDiff    = (double *) malloc(sizeof(double) * nxy);  
  wavRcnFrm1 = (double *) malloc(sizeof(double) * nxy);  
  wavRcnDiff = (double *) malloc(sizeof(double) * nxy);  
  diffd      = (double *) malloc(sizeof(double) * nxy);  
  rcnDiffd   = (double *) malloc(sizeof(double) * nxy);  

  frm1Ed     = (double *) malloc(sizeof(double) * nxE * nyE);  
  frm1E      = (unsigned char *) malloc(sizeof(unsigned char) * nxE * nyE);

  //read file from PGM and store into frm1  
  frameNo = START_FRAME;  
  sprintf(fileName, INPUT_STRING, frameNo);  
  readPgm(frm1, fileName, nx, ny);  

  //after some operations

  //write into a new PGM file  
   sprintf(fileName, "predictDb%03d.pgm", frameNo);  
   writePgm(predictDb, fileName, nx, ny);  

  return 0; //end of main function   
}  

//read original frame  
void readPgm(unsigned char *frame, char * fileName, int nx, int ny) {  
  int i, j;  
  FILE *file;  
  char str[128];  

  file = fopen(fileName,"r");  
  if (file == 0) {  
    printf("Open error in File read \n");  
      }  
  fgets(str, 100, file);  
  for(j = 0; j < ny; j++) {  
      for(i = 0; i < nx; i++) {  
    fscanf(file,"%d", (int *)&frame[i + nx * j]);  
      }  
  }  
  fclose(file);  
}  


//create frame  
void writePgm(unsigned char *frame, char *fileName, int nx, int ny){  
  int i, j;  
  FILE *file;  

  file = fopen(fileName, "w");  
  fprintf(file, "P2 %d %d 255\n", nx, ny);  
  for(j = 0; j < ny; j++) {  
    for(i = 0; i < nx; i++) {  
      fprintf(file,"%d ", frame[i + nx * j]);  
    }  
    fprintf(file, "\n");  
  }  
  fclose(file);  
}  

Can anyone help identify what the problem is? Thank you

skyjuice
  • 1
  • 2
  • It doesn't look like you initialize `nxy` before you use it. After that none of your `malloc`s will be correct. – Dave Apr 16 '12 at 03:56

3 Answers3

1

You never initialize nxy and most other variables you use in the calls to malloc(). Those variables then can contain random values and you will not allocate the correct amounts of memory.

sth
  • 222,467
  • 53
  • 283
  • 367
  • Sorry, I actually did initialize nyz but did not include it in my code above. So I guess the problem is not due to this. Anymore possible causes? – skyjuice Apr 16 '12 at 04:39
1

This code

int   /* ... */, nxy;   
frm1  = (unsigned char *) malloc(sizeof(unsigned char) * nxy);   

means that you allocate memory based on uninitialized value (nxy), which can be anything (whatever garbage is in memory where nxy is allocated.

Then you pass this unknown length buffer to

readPgm(frm1, fileName, nx, ny);

and attempt to access frame[i + nx * j]

If nxy is less than nx*ny, you are corrupting memory by writing past the allocated space.

To fix, make sure you initialize all variables properly. E.g.:

int nxy = nx*ny;

Also, see this SO question on why you should not cast the return value of malloc -- void * (the return type of malloc) will be implicitly converted to the correct type

Community
  • 1
  • 1
Attila
  • 28,265
  • 3
  • 46
  • 55
  • Sorry, I actually did initialize nyz but did not include it in my code above. So I guess the problem is not due to this. Anymore possible causes? – skyjuice Apr 16 '12 at 06:31
  • The other problem is that you allocate nxy _characters_ worth of data for the frame, but when access it, you cast the pointer to pointer-to-_int_. You either need to read a simple unsigned char in `fscanf`, or change `sizeof(char)` to `sizeof(int)` when allocating the frame (and change its type to `int*` as well). In either case you will not need the cast in the `fscanf` – Attila Apr 16 '12 at 06:48
0

This does not appear to be Linux specific - the C code should work in any environment, even Windows.

Compile with gcc -g (or even gcc -ggdb) to get line numbers in that error backtrace (and to enable easier debugging with gdb).

I don't see where you call free() to release memory that you allocated using malloc(). If you don't, the memory is released when the process exits. I suspect you have an off-by-one that overflows into memory that contains a pointer, and overwrites the address in the pointer with garbage. Then when you try to release a chunk of memory that begins at this "address" the operation fails. Compile with debug information, run your program in gdb (gdb --args ./myprogram arg1 arg2, start, next, step, continue) and see where the problem occurs. To help debug memory issues (like writes outside a buffer) use valgrind.

Z.T.
  • 939
  • 8
  • 20