1
votes

i tested an sample try-catch block with a simple memory allocation program in a embedded device which runs with only 64MB RAM with customized linux OS 32-bit Xscale Arm architecture.My intention was to verify whether a normal try catch block will work when there is no memory on this device.Im listing the code as below.Assume this as program1.

#include "stdio.h"
#include "stdlib.h"
int main()
{
    int count;
    int *q[409600];
    printf("\nHeap Leak Starting at..");
    system("date");
    fflush(stdout);
    printf("\n, Count is located at ,%p,",&count);
    for(count=0;count<409600;count++)
    {
            printf("\nCount = ,%d,",count);
            int i=2;
            try
            {
                    fflush(stdout);
                    q[count] = new int[409600];
                    printf("New Success.Allocated %ld Bytes at %p.Difference = 0x%x,\n",(i*100000),q[count],(long)(&i) - (long)q[count]);
                    fflush(stdout);
            }
            catch(...)
            {
                            printf("\nException Caught...New Failed..No Memory Available.\n");
                            fflush(stdout);
                            exit(1);
            }
    }
}

Output of Program1:

Thu Jul 31 20:38:00 UTC 2014
Heap Leak Starting at..,

Count is located at ,0xbffffc48,

Count = ,0,New Success.Allocated 200000 Bytes at 0x402c0008.Difference = 0x7fbafc3c,

Count = ,1,New Success.Allocated 200000 Bytes at 0x40451008.Difference = 0x7fa1ec3c,

Count = ,2,New Success.Allocated 200000 Bytes at 0x405e2008.Difference = 0x7f88dc3c,

Count = ,3,New Success.Allocated 200000 Bytes at 0x40773008.Difference = 0x7f6fcc3c,

........The count goes on........

Count = ,1954,New Success.Allocated 200000 Bytes at 0xbf854008.Difference = 0x61bc3c,

Count = ,1955,New Success.Allocated 200000 Bytes at 0xbf9e5008.Difference = 0x48ac3c,

Count = ,1956,New Success.Allocated 200000 Bytes at 0xbfb76008.Difference = 0x2f9c3c,

Count = ,1957,
Exception Caught...New Failed..No Memory Available.

Now this is an expected behaviour.Since no memory is there,Exception is throwed.

Then i modified the line "q[count] = new int[409600]" to "q[count] = new int[100000]".Lets assume this as program2.I recompiled the program and executed on the same device.

Output of Program2:

Thu Jul 31 20:39:43 UTC 2014

Heap Leak Starting at..,

Count is located at ,0xbffffc48,

Count = ,0,New Success.Allocated 200000 Bytes at 0x402c0008.Difference = 0x7fbafc3c,

Count = ,1,New Success.Allocated 200000 Bytes at 0x40322008.Difference = 0x7fb4dc3c,

Count = ,2,New Success.Allocated 200000 Bytes at 0x40384008.Difference = 0x7faebc3c,

Count = ,3,New Success.Allocated 200000 Bytes at 0x403e6008.Difference = 0x7fa89c3c,

............The count goes on.............

Count = ,5215,New Success.Allocated 200000 Bytes at 0x87d00018.Difference = 0x3816fc2c,

Count = ,5216,New Success.Allocated 200000 Bytes at 0x87d61aa0.Difference = 0x3810e1a4,

Count = ,5217,New Success.Allocated 200000 Bytes at 0x87e00018.Difference = 0x3806fc2c,

Count = ,5218,New Success.Allocated 200000 Bytes at 0x87e61aa0.Difference = 0x3800e1a4,

Count = ,5219,New Success.Allocated 200000 Bytes at 0x87f00018.Difference = 0x37f6fc2c,

Count = ,5220,

And at this point,the process gets hanged forever at the New operator.I could not access the terminal even if i run the process in background.

Now i am confused on noticing this different behaviour of new.Please not that in the exception throwing case im allocating a large size(409600) than the case where the process gets hanged(100000). Can someone help me in clarifying this different behaviour of New? Please share your thoughts and some clues as this breakthrough is required for me to debug an validation bug reported in the same device.

PS:Ignore the number 200000 as i have printed it wrongly.

1
On one hand you have the C++ specification which tells you that new will throw an exception when it can't allocate memory. On the other hand you have the Linux kernel which will randomly kill processes when the system is out of memory. - Some programmer dude
Hi @JoachimPileborg : do you mean that the kernal is killing this process when it runs out of memory? i.e when runned with 100000 ? whereas when runned with 409600 it would not kill? - ArunkumarRavi
The kernel can kill a process when the system is low on memory, but it doesn't have to be the process that causes the problem, the Linux kernel out-of-memory handler is famous for killing processes randomly. - Some programmer dude
@JoachimPileborg : If that is the case,why would the console/device go to non-responsive state? Becasue with the console i can find the list of processes alive yet.. In this case if the system gets hange ..It needs to be force restarted .. - ArunkumarRavi

1 Answers

0
votes

The printf and fflush routines may be trying to allocate memory. They may also be locking or doing some other synchronization that causes a deadlock. Memory may be required to allocate the exception object (though hopefully any self-respecting runtime handles this case).

Most C library call's behavior when there is no memory left may not be well specified (perhaps they deadlock or go into a loop, or perhaps they leave something corrupted so that when your 'catch' tries to print, it deadlocks). Most libraries do not have well-defined semantics for how they behave when they run out of memory (or even if they need to use any memory).

Attach a debugger or get a backtrace to see where your process is hanging/waiting.

Alternatively, you can test my hypothesis by using API calls that are very unlikely to allocate any memory in their implementation:

  • exit is a good for identifying which part of the code exited (pass a different number)
  • write is generally allocation-free (but its hard to pass run-time strings). Something like: write(1, "I am here", strlen("I am here")); (There is no need to flush after a direct write call.)