sbrk() problem in QNX

Please, help!

I am trying to port a POSIX application to QNX 6.2.1, which makes use of sbrk(), but sbrk() appears to be broken. Is this right? Please, look at the following output:

Not really code, just output: Current break value after sbrk(0x0) = 0x804a040 New break value after sbrk(0x3100) = 0x804a040 New break value after sbrk(0x0200) = 0x8052100 New break value after sbrk(0x0000) = 0x8053200 New break value after sbrk(0x0000) = 0x8053200

According to the QNX 6.2.1 docs, sbrk(0x0) should return the current break value, ok? Now, sbrk(0x3100) should increase it by 0x3100, but nothing happens (it should be 0x804d140, but it returns the old break value). sbrk(0x0200) should increase it by 0x0200, this does not happen, etc.

If I try to use brk() (not sbrk()) to restore the break point to the one obtained from sbrk(0x0000), the program core dumps.

Is this a well-known bug? Is there a workaround?

Please, pretty please, help me.

Thank you very much for your time.

John Barnes

Please post your test program.
BTW, have you tried your test program on another Unix (Linux, Solaris) and see if it works as you expected? This should confirm whether it is a QNX “bug” ;)

Here is the latest version of my test program:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main( void )
{
   void *breakval, *oldbreakval;

   breakval = sbrk(0x0);
   oldbreakval = breakval;
   printf( "Current break value after sbrk(0x0) \t%p\n", breakval);

   breakval = sbrk(0x3100);
   printf( "New break value after sbrk(0x3100) \t%p\n", breakval);

   breakval = sbrk(0x0200);
   printf( "New break value after sbrk(0x0200) \t%p\n", breakval);

   breakval = sbrk(0x0000);
   printf( "New break value after sbrk(0x0000) \t%p\n", breakval);

   breakval = sbrk(0x0000);
   printf( "New break value after sbrk(0x0000) \t%p\n", breakval);

   if(brk(oldbreakval)<0){
      printf("brk error\n");
      return -1;
   }

   breakval = sbrk(0x0000);
   printf( "New break value after brk( %x ) \t%p\n", oldbreakval, breakval);

   return EXIT_SUCCESS;
}

Here is the output for the Linux (Fedora Core 3, x86) run:

Current break value after sbrk(0x0)          0x82ee000
New break value after sbrk(0x3100)          0x82ee000
New break value after sbrk(0x0200)          0x82f1100
New break value after sbrk(0x0000)          0x82f1300
New break value after sbrk(0x0000)          0x82f1300
New break value after brk( 82ee000)         0x82ee000

Everything appears to work as expected in Linux (sbrk() returns a pointer to the beginning of the newly created region of memory).

Here is the output for the QNX 6.2.1 (x86) run:

Current break value after sbrk(0x0)          804a098
New break value after sbrk(0x3100)          804a098
New break value after sbrk(0x0200)          8052100
New break value after sbrk(0x0000)          8053200
New break value after sbrk(0x0000)          8053200
Memory fault (core dumped)

As you can see, when asked for 0x3100 more memory space, QNX appears to return (0x8052100 - 0x804a908), which is 0x8068 (or 32872 bytes decimal). When asked for 0x0200, QNX appears to return (0x8053200 - 0x8052100), which is 0x1100 (or 4352 bytes decimal). After all that, the program core dumps in the brk() library call.

Could the explanation be that QNX allocates memory in large chunks and then has trouble reducing the breakpoint (I think I read in a news group somewhere that QNX is afraid some memory headers or something may be damaged)? If so, where is this documented? How come it is not documented in the material that comes with QNX 6.2.1?

Please help me by explaining to me how all this works and how to workaround this problem.

Thank you very much for your time.

John Barnes

brk/sbrk is not really portable as I heard. You should probably use malloc, etc. instead.

My guess is (in QNX) printf, etc. in your code uses malloc to access some internal memory structure. Since malloc uses sbrk to get some memory, YOUR sbrk will “see” a larger size. stepping on each other’s memory will cause a core dump.

Anyway, I think only people like Colin who knows the internals of QNX brk/sbrk implementation can give a definite answer.

Looking into it, sbrk is never going to be useful as implemented on QNX. I think it’s baggage from an earlier time…

The problem is that malloc/free is based on mmap()/munmap(), and thus we have a ‘sparse’ heap. The curbrk value is never updated, execpt by brk itself (and a few mysterious functions like smalloc()).

This means that the curbrk value is never going to be right, so trying to set the curbrk back to the oldbrk value is going to unmap a whole load of someone elses data at worst… no wonder the app crashes.

There is a PR in our database to doc this - I think that the function should be fully de-supported…

Therefore, when a malloc is issued it does not call the sbrk at all, am I right?

I thought that sbrk was called when the process needed more memory than the one associated to it.

I had some problems with memory and I found a underrun in my programs (several tasks running altogether) but I wasn’t be able to find it even using the malloc_g library because it gave me nonsense output such us that the underrun could be caused by a call to a function out of the memory space of the process code segment.

I overcome this problem by re-structuring the program and not using so many times dynamic memory management (as many calls to malloc as possible).