Why does new allocate more memory than there is??

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Alan Gifford

    Why does new allocate more memory than there is??

    I wrote a program to make sure that new would throw a bad_alloc
    exception if more memory was requested than was available. On my
    system, new allocates up to 2931 MBs of memory (I don't have that
    much, not even with swap) before throwing an exception. When the
    program tries to fill in the allocated memory with data, it is killed
    after using up the available memory.

    Does anyone know why the exception is not being thrown until well
    after all memory has been allocated? Here is the code...

    #include <new.h>
    #include <iostream.h>
    #include <unistd.h>

    #define ARRAY_SIZE1 131072 // # of doubles to take up 1MB of memory
    #define ARRAY_SIZE2 3072 // How many MBs do you want to attempt?

    int main(void) {
    cout << "This is a test to catch for problems with new allocating memory."
    << endl;
    cout << "You might want to watch your memory resource meter."
    << endl;
    sleep(2);

    double* dblPtr[ARRAY_SIZE2];

    cout << "\nAttempti ng to allocate "
    << ((sizeof(double ) * ARRAY_SIZE1 * ARRAY_SIZE2) / (1024 * 1024))
    << " megabytes." << endl;

    int arraySize = ARRAY_SIZE2;
    for (int i=0; i < ARRAY_SIZE2; i++) {
    try {
    dblPtr[i] = new double[ARRAY_SIZE1];
    if (dblPtr[i] == NULL) {
    cout << "\nError, pointer was set to NULL." << endl;
    }
    }
    catch (bad_alloc ex) {
    cout << "\nExceptio n caught: " << ex.what() << endl;
    arraySize = i - 1;
    cout << "Setting arraySize to " << arraySize << endl;
    break;
    }
    }

    cout << "\nOstensib ly allocated "
    << ((sizeof(double ) * ARRAY_SIZE1 * arraySize) / (1024 * 1024))
    << " megabytes of memory." << endl;
    cout << "Let's see what happens when we try to fill it." << endl;
    sleep(2);

    cout << "\nBeginnin g filling arrays. If the program is killed, it means the"
    << endl;
    cout << "program was not actually able to fill the memory it has been "
    << "allocated. " << endl;

    double dummy = 6.67259e-11;
    double* tmp;
    for (int i=0; i < arraySize; i++) {
    tmp = dblPtr[i];
    for (int j=0; j < ARRAY_SIZE1; j++) {
    tmp[j] = dummy;
    }
    }
    return 0;
    }
  • cpp_weenie

    #2
    Re: Why does new allocate more memory than there is??


    "Alan Gifford" <siliconbadger@ yahoo.com> wrote in message
    news:f299e551.0 310171402.79103 7a0@posting.goo gle.com...[color=blue]
    > I wrote a program to make sure that new would throw a bad_alloc
    > exception if more memory was requested than was available. On my
    > system, new allocates up to 2931 MBs of memory (I don't have that
    > much, not even with swap) before throwing an exception. When the
    > program tries to fill in the allocated memory with data, it is killed
    > after using up the available memory.
    >
    > Does anyone know why the exception is not being thrown until well
    > after all memory has been allocated? Here is the code...
    >
    > #include <new.h>
    > #include <iostream.h>
    > #include <unistd.h>
    >
    > #define ARRAY_SIZE1 131072 // # of doubles to take up 1MB of memory
    > #define ARRAY_SIZE2 3072 // How many MBs do you want to attempt?
    >
    > int main(void) {
    > cout << "This is a test to catch for problems with new allocating[/color]
    memory."[color=blue]
    > << endl;
    > cout << "You might want to watch your memory resource meter."
    > << endl;
    > sleep(2);
    >
    > double* dblPtr[ARRAY_SIZE2];
    >
    > cout << "\nAttempti ng to allocate "
    > << ((sizeof(double ) * ARRAY_SIZE1 * ARRAY_SIZE2) / (1024 * 1024))
    > << " megabytes." << endl;
    >
    > int arraySize = ARRAY_SIZE2;
    > for (int i=0; i < ARRAY_SIZE2; i++) {
    > try {
    > dblPtr[i] = new double[ARRAY_SIZE1];
    > if (dblPtr[i] == NULL) {
    > cout << "\nError, pointer was set to NULL." << endl;
    > }
    > }
    > catch (bad_alloc ex) {
    > cout << "\nExceptio n caught: " << ex.what() << endl;
    > arraySize = i - 1;
    > cout << "Setting arraySize to " << arraySize << endl;
    > break;
    > }
    > }
    >
    > cout << "\nOstensib ly allocated "
    > << ((sizeof(double ) * ARRAY_SIZE1 * arraySize) / (1024 * 1024))
    > << " megabytes of memory." << endl;
    > cout << "Let's see what happens when we try to fill it." << endl;
    > sleep(2);
    >
    > cout << "\nBeginnin g filling arrays. If the program is killed, it means[/color]
    the"[color=blue]
    > << endl;
    > cout << "program was not actually able to fill the memory it has been "
    > << "allocated. " << endl;
    >
    > double dummy = 6.67259e-11;
    > double* tmp;
    > for (int i=0; i < arraySize; i++) {
    > tmp = dblPtr[i];
    > for (int j=0; j < ARRAY_SIZE1; j++) {
    > tmp[j] = dummy;
    > }
    > }
    > return 0;
    > }[/color]

    A range of virtual addresses is set aside for your use by new, but pages of
    those addresses aren't backed by real storage (either physical mem. or swap)
    until actually touched...

    Hmmm... I just had an interesting thought. If you had been allocating a
    class type with a non-trivial constructor (rather than a double), I suppose
    the memory when have been touched right away during construction of the
    objects and then you would have seen an exception right away.

    Any thoughts on that anyone? Any deeper issues here that I'm not
    considering right off-the-cuff?


    Comment

    • Alan Gifford

      #3
      Re: Why does new allocate more memory than there is??

      "cpp_weenie " <cpp@weenie.com > wrote in message
      [color=blue]
      > A range of virtual addresses is set aside for your use by new, but pages of
      > those addresses aren't backed by real storage (either physical mem. or swap)
      > until actually touched...
      >
      > Hmmm... I just had an interesting thought. If you had been allocating a
      > class type with a non-trivial constructor (rather than a double), I suppose
      > the memory when have been touched right away during construction of the
      > objects and then you would have seen an exception right away.
      >
      > Any thoughts on that anyone? Any deeper issues here that I'm not
      > considering right off-the-cuff?[/color]

      Well, I'm not so much concerned with what goes on behind the scenes to
      create the problem. I guess I am asking why it happens this way. I
      don't really understand the purpose of a bad_alloc exception if it's
      not going to be thrown every time there was a bad allocation attempt.

      I am not an experienced programmer, so I don't know for sure that this
      is the main purpose of the bad_alloc exception, but it certainly seems
      like it is not operating the way it's supposed to.

      Bottom line: I'd just like to know, am I wrong to think that bad_alloc
      should be thrown in this case, or is the compiler doing something
      wrong? I've performed this test on several Linux machines as well as
      a Mac running OS 10.1, and they both have the same error. I was using
      gcc (g++) in all systems.

      Thanks!
      Alan

      Comment

      • Dave

        #4
        Re: Why does new allocate more memory than there is??


        "Alan Gifford" <siliconbadger@ yahoo.com> wrote in message
        news:f299e551.0 310231913.7724f 37c@posting.goo gle.com...[color=blue]
        > "cpp_weenie " <cpp@weenie.com > wrote in message
        >[color=green]
        > > A range of virtual addresses is set aside for your use by new, but pages[/color][/color]
        of[color=blue][color=green]
        > > those addresses aren't backed by real storage (either physical mem. or[/color][/color]
        swap)[color=blue][color=green]
        > > until actually touched...
        > >
        > > Hmmm... I just had an interesting thought. If you had been allocating a
        > > class type with a non-trivial constructor (rather than a double), I[/color][/color]
        suppose[color=blue][color=green]
        > > the memory when have been touched right away during construction of the
        > > objects and then you would have seen an exception right away.
        > >
        > > Any thoughts on that anyone? Any deeper issues here that I'm not
        > > considering right off-the-cuff?[/color]
        >
        > Well, I'm not so much concerned with what goes on behind the scenes to
        > create the problem. I guess I am asking why it happens this way. I
        > don't really understand the purpose of a bad_alloc exception if it's
        > not going to be thrown every time there was a bad allocation attempt.
        >
        > I am not an experienced programmer, so I don't know for sure that this
        > is the main purpose of the bad_alloc exception, but it certainly seems
        > like it is not operating the way it's supposed to.
        >
        > Bottom line: I'd just like to know, am I wrong to think that bad_alloc
        > should be thrown in this case, or is the compiler doing something
        > wrong? I've performed this test on several Linux machines as well as
        > a Mac running OS 10.1, and they both have the same error. I was using
        > gcc (g++) in all systems.
        >
        > Thanks!
        > Alan[/color]

        I think that your expectations are very reasonable but, nevertheless, I
        don't think you will necessarily see the behavior you expect for the reason
        I stated. I am in total agreement with you that a bad_alloc being thrown
        well after the fact doesn't seem to make a lot of sense. Nevertheless,
        reality is that individual pages may not be backed by actual storage until
        touched. Though you and I find your compiler's behavior illogical, I don't
        believe it is "wrong" in the sense that there is a bug. I think it is
        exhibiting the behavior intended by the compiler writers.

        I'll leave it to others more knowledgeable than I to comment on why pages
        might not be backed by actual storage until they're touched. I'd be very
        interested to know the reason.


        Comment

        • tom_usenet

          #5
          Re: Why does new allocate more memory than there is??

          On 23 Oct 2003 20:13:48 -0700, siliconbadger@y ahoo.com (Alan Gifford)
          wrote:
          [color=blue]
          >"cpp_weenie " <cpp@weenie.com > wrote in message
          >[color=green]
          >> A range of virtual addresses is set aside for your use by new, but pages of
          >> those addresses aren't backed by real storage (either physical mem. or swap)
          >> until actually touched...
          >>
          >> Hmmm... I just had an interesting thought. If you had been allocating a
          >> class type with a non-trivial constructor (rather than a double), I suppose
          >> the memory when have been touched right away during construction of the
          >> objects and then you would have seen an exception right away.
          >>
          >> Any thoughts on that anyone? Any deeper issues here that I'm not
          >> considering right off-the-cuff?[/color]
          >
          >Well, I'm not so much concerned with what goes on behind the scenes to
          >create the problem. I guess I am asking why it happens this way. I
          >don't really understand the purpose of a bad_alloc exception if it's
          >not going to be thrown every time there was a bad allocation attempt.
          >
          >I am not an experienced programmer, so I don't know for sure that this
          >is the main purpose of the bad_alloc exception, but it certainly seems
          >like it is not operating the way it's supposed to.
          >
          >Bottom line: I'd just like to know, am I wrong to think that bad_alloc
          >should be thrown in this case, or is the compiler doing something
          >wrong? I've performed this test on several Linux machines as well as
          >a Mac running OS 10.1, and they both have the same error. I was using
          >gcc (g++) in all systems.[/color]

          The problem is that bad_alloc doesn't fit well with modern virtual
          paging memory systems. On some systems, for performance reasons,
          memory isn't actually set aside when you call malloc/new, since where
          the pages of memory will come from (disk, main memory, cache?) is only
          decided when you try to access the memory. This makes it impossible
          for the system to know for sure whether it can allocate a chunk of
          memory when you make the allocation, since, e.g., you might deallocate
          another chunk before trying to access this one, thus making room
          available.

          This means that you have to rely on systems other than bad_alloc to
          handle low memory on some modern OSes. On modern OSes, you'll be into
          major performance problems long before you actually run out of memory
          (paging to disk will cause hard disk thrashing), so you need to
          monitor how much memory your program is using and how much is
          available using OS specific functions.

          It's a shame that bad_alloc is largely useless on modern desktop
          platforms.

          Tom

          Comment

          Working...