Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. Memory allocation woes

Memory allocation woes

Scheduled Pinned Locked Moved Clever Code
12 Posts 8 Posters 34 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • 0 Offline
    0 Offline
    0x3c0
    wrote on last edited by
    #1

    This was right under my nose for about two weeks before I noticed. Vigorous face-palming ensued when I noticed the difference. It was in some really (pre-heap) simple memory allocation. For some reason, I was overwriting memory starting at odd locations. This broke my IDT and GDT, so I couldn't even debug properly My memory allocation was quite simple. It took the kernel's ending address in memory, page-aligned it and added 0x1000. When a small amount of memory was requested, it simply added the memory size to the ending address and returned the previous ending address. It turns out that I was allocating memory at 0x0; for those who don't know why that's bad, it can overwrite the console memory, ACPI tables, and the stack. The strange thing was, my ending address was fine. The problem came from this line:

    uint MemoryAccess::placementAddress = (uint)&end & 0xFFFFF000 + 0x1000;

    Because of operator precedence, the AND was getting performed in the wrong order. Two characters fixed the problem: ( and )

    uint MemoryAccess::placementAddress = ((uint)&end & 0xFFFFF000) + 0x1000;

    L P J 3 Replies Last reply
    0
    • 0 0x3c0

      This was right under my nose for about two weeks before I noticed. Vigorous face-palming ensued when I noticed the difference. It was in some really (pre-heap) simple memory allocation. For some reason, I was overwriting memory starting at odd locations. This broke my IDT and GDT, so I couldn't even debug properly My memory allocation was quite simple. It took the kernel's ending address in memory, page-aligned it and added 0x1000. When a small amount of memory was requested, it simply added the memory size to the ending address and returned the previous ending address. It turns out that I was allocating memory at 0x0; for those who don't know why that's bad, it can overwrite the console memory, ACPI tables, and the stack. The strange thing was, my ending address was fine. The problem came from this line:

      uint MemoryAccess::placementAddress = (uint)&end & 0xFFFFF000 + 0x1000;

      Because of operator precedence, the AND was getting performed in the wrong order. Two characters fixed the problem: ( and )

      uint MemoryAccess::placementAddress = ((uint)&end & 0xFFFFF000) + 0x1000;

      L Offline
      L Offline
      leppie
      wrote on last edited by
      #2

      Computafreak wrote:

      Two characters fixed the problem: ( and )

      Once again LISP-based languages show their superiority ;P

      xacc.ide - now with TabsToSpaces support
      IronScheme - 1.0 beta 2 - out now!
      ((lambda (x) `((lambda (x) ,x) ',x)) '`((lambda (x) ,x) ',x))

      1 Reply Last reply
      0
      • 0 0x3c0

        This was right under my nose for about two weeks before I noticed. Vigorous face-palming ensued when I noticed the difference. It was in some really (pre-heap) simple memory allocation. For some reason, I was overwriting memory starting at odd locations. This broke my IDT and GDT, so I couldn't even debug properly My memory allocation was quite simple. It took the kernel's ending address in memory, page-aligned it and added 0x1000. When a small amount of memory was requested, it simply added the memory size to the ending address and returned the previous ending address. It turns out that I was allocating memory at 0x0; for those who don't know why that's bad, it can overwrite the console memory, ACPI tables, and the stack. The strange thing was, my ending address was fine. The problem came from this line:

        uint MemoryAccess::placementAddress = (uint)&end & 0xFFFFF000 + 0x1000;

        Because of operator precedence, the AND was getting performed in the wrong order. Two characters fixed the problem: ( and )

        uint MemoryAccess::placementAddress = ((uint)&end & 0xFFFFF000) + 0x1000;

        P Offline
        P Offline
        Phil J Pearson
        wrote on last edited by
        #3

        Computafreak wrote:

        the AND was getting performed in the wrong order

        No. The AND was being performed in the RIGHT order. It just wasn't the order you wanted!

        Phil


        The opinions expressed in this post are not necessarily those of the author, especially if you find them impolite, inaccurate or inflammatory.

        M 1 Reply Last reply
        0
        • P Phil J Pearson

          Computafreak wrote:

          the AND was getting performed in the wrong order

          No. The AND was being performed in the RIGHT order. It just wasn't the order you wanted!

          Phil


          The opinions expressed in this post are not necessarily those of the author, especially if you find them impolite, inaccurate or inflammatory.

          M Offline
          M Offline
          Michael Bookatz
          wrote on last edited by
          #4

          precedent order... easy to forget!

          0 1 Reply Last reply
          0
          • M Michael Bookatz

            precedent order... easy to forget!

            0 Offline
            0 Offline
            0x3c0
            wrote on last edited by
            #5

            Even harder when I never learned it (apart from the basic mathematical one) in the first place

            G 1 Reply Last reply
            0
            • 0 0x3c0

              Even harder when I never learned it (apart from the basic mathematical one) in the first place

              G Offline
              G Offline
              Gary R Wheeler
              wrote on last edited by
              #6

              That's why I always fully parenthesize expressions. I've used too many languages and too many compilers to remember the arcane rules when just inserting the parenteses fixes the problem once and for all.

              Software Zen: delete this;
              Fold With Us![^]

              C S 2 Replies Last reply
              0
              • G Gary R Wheeler

                That's why I always fully parenthesize expressions. I've used too many languages and too many compilers to remember the arcane rules when just inserting the parenteses fixes the problem once and for all.

                Software Zen: delete this;
                Fold With Us![^]

                C Offline
                C Offline
                Chris Losinger
                wrote on last edited by
                #7

                yeah, same here. i've been bitten by these kinds of precedence tricks too many times.

                image processing toolkits | batch image processing

                1 Reply Last reply
                0
                • 0 0x3c0

                  This was right under my nose for about two weeks before I noticed. Vigorous face-palming ensued when I noticed the difference. It was in some really (pre-heap) simple memory allocation. For some reason, I was overwriting memory starting at odd locations. This broke my IDT and GDT, so I couldn't even debug properly My memory allocation was quite simple. It took the kernel's ending address in memory, page-aligned it and added 0x1000. When a small amount of memory was requested, it simply added the memory size to the ending address and returned the previous ending address. It turns out that I was allocating memory at 0x0; for those who don't know why that's bad, it can overwrite the console memory, ACPI tables, and the stack. The strange thing was, my ending address was fine. The problem came from this line:

                  uint MemoryAccess::placementAddress = (uint)&end & 0xFFFFF000 + 0x1000;

                  Because of operator precedence, the AND was getting performed in the wrong order. Two characters fixed the problem: ( and )

                  uint MemoryAccess::placementAddress = ((uint)&end & 0xFFFFF000) + 0x1000;

                  J Offline
                  J Offline
                  Jorgen Sigvardsson
                  wrote on last edited by
                  #8

                  Yep. Whenever & and | are involved, I use parenthesizes.

                  0 1 Reply Last reply
                  0
                  • J Jorgen Sigvardsson

                    Yep. Whenever & and | are involved, I use parenthesizes.

                    0 Offline
                    0 Offline
                    0x3c0
                    wrote on last edited by
                    #9

                    A lesson I learned bitterly. I wasted far too much time on that. The most irritating thing was that I had a little problem with paging, so decided to rewrite that particular class. Now I don't need that function to begin with - I use a ported liballoc instead. It's sad - if I had tackled the rewrite first, that problem would have resolved itself :sigh:

                    1 Reply Last reply
                    0
                    • G Gary R Wheeler

                      That's why I always fully parenthesize expressions. I've used too many languages and too many compilers to remember the arcane rules when just inserting the parenteses fixes the problem once and for all.

                      Software Zen: delete this;
                      Fold With Us![^]

                      S Offline
                      S Offline
                      supercat9
                      wrote on last edited by
                      #10

                      Borland's compilers in the 1980's-1990's had an option to produce a warning if certain variations in precedence rules would cause expressions to parse differently. I don't remember the exact circumstances that would yield a warning, but I think it would squawk (if the option was turned on) if reversing the precedence of the shift and bitwise operators would change the code. Sometimes appeasing the compiler required adding ugly parenthesis in cases where the 'natural' reading would have been the correct one, but generally the warning was very helpful. Nowadays it seems Microsoft's compilers like to squawk at silly things while ignoring more serious ones. Coercing from double to single in vb.net without a cast? Error. Trying to 'and' a 64-bit flag with 'not &h80000000' or 'not someUnsignedIntVar'? No squawk, but clears the upper 32 bits of the flag.

                      G 1 Reply Last reply
                      0
                      • S supercat9

                        Borland's compilers in the 1980's-1990's had an option to produce a warning if certain variations in precedence rules would cause expressions to parse differently. I don't remember the exact circumstances that would yield a warning, but I think it would squawk (if the option was turned on) if reversing the precedence of the shift and bitwise operators would change the code. Sometimes appeasing the compiler required adding ugly parenthesis in cases where the 'natural' reading would have been the correct one, but generally the warning was very helpful. Nowadays it seems Microsoft's compilers like to squawk at silly things while ignoring more serious ones. Coercing from double to single in vb.net without a cast? Error. Trying to 'and' a 64-bit flag with 'not &h80000000' or 'not someUnsignedIntVar'? No squawk, but clears the upper 32 bits of the flag.

                        G Offline
                        G Offline
                        Gary R Wheeler
                        wrote on last edited by
                        #11

                        Bit-twiddling in VB just seems like you're asking for trouble.

                        Software Zen: delete this;
                        Fold With Us![^]

                        S 1 Reply Last reply
                        0
                        • G Gary R Wheeler

                          Bit-twiddling in VB just seems like you're asking for trouble.

                          Software Zen: delete this;
                          Fold With Us![^]

                          S Offline
                          S Offline
                          supercat9
                          wrote on last edited by
                          #12

                          Gary R. Wheeler wrote:

                          Bit-twiddling in VB just seems like you're asking for trouble.

                          The same problem exists in C. If I were writing a language spec, I would specify that the 'not' operator shall always behave as though it returned the longest existing integer type, and that signed/unsigned comparisons shall always behave in numerically-correct fashion (i.e. if the signed number is negative, it's less than the signed one; otherwise the values compare numerically). Actually, I'd specify that any integer expression all of whose whose intermediate subexpressions fit in the largest integer type must be evaluated as though all calculations were done in that largest type. In many cases, a halfway-intelligent compiler should be able to figure out what size operands are actually necessary, and I can't think of any case where such behavior would break decently-written code. Do you know of any languages that work that way? BTW, a couple more things: (1) a decent compiler should be able to recognize the cases where casting to a long doesn't really mean casting to a long, such as "longvar = int1 * (long)int2;" or "longvar &= ~2;". In the former case, the hardware should use one int*int->long multiply rather than sign extending the two integers, performing four uint*uint->ulong multiplies, and adding up the partial products; a decent compiler should also recognize "longvar &= ~(long)smallpositivevalue;" and not bother doing anything with the upper bits of longvar; (2) I wonder why more languages and CPUs don't have an "and not" operator/instruction. I think Vax Basic included such an operator, and the ARM instruction set does, but I've not seen them often. One more thing: I think it's cool that the formula for computing sum(i=0..inf)(2^i) yields -1. So computers and "real math" agree.

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups