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. Caution! No sign ahead!

Caution! No sign ahead!

Scheduled Pinned Locked Moved Clever Code
c++comhelplearning
10 Posts 6 Posters 12 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.
  • C Offline
    C Offline
    Chris Losinger
    wrote on last edited by
    #1

    i found this one a couple of days ago. it's the inner loop in a Gaussian blur. it's running a kernel over a rectangular section of pixels...

    double v = 0, s = 0;

    for (int cc=start;cc < stop;cc++)
    {
    double k = kernel[center+cc];
    v += pArray[cc * uCPP] * k;
    s += k;
    }

    uCPP is unsigned. start can be negative. and when start is negative, cc * uCPP is probably going to give an integer overflow, since cc will be implicitly cast into a REALLY BIG unsigned integer... and then you'll get an access violation, since pArray really isn't that big. oddly, it took an x64 build for this to give an A.V. - it worked without crashing (somehow) on all the Win32 builds we had. the fix, of course, is: cc * (int)uCPP alas.

    image processing | blogging

    PJ ArendsP M D 3 Replies Last reply
    0
    • C Chris Losinger

      i found this one a couple of days ago. it's the inner loop in a Gaussian blur. it's running a kernel over a rectangular section of pixels...

      double v = 0, s = 0;

      for (int cc=start;cc < stop;cc++)
      {
      double k = kernel[center+cc];
      v += pArray[cc * uCPP] * k;
      s += k;
      }

      uCPP is unsigned. start can be negative. and when start is negative, cc * uCPP is probably going to give an integer overflow, since cc will be implicitly cast into a REALLY BIG unsigned integer... and then you'll get an access violation, since pArray really isn't that big. oddly, it took an x64 build for this to give an A.V. - it worked without crashing (somehow) on all the Win32 builds we had. the fix, of course, is: cc * (int)uCPP alas.

      image processing | blogging

      PJ ArendsP Offline
      PJ ArendsP Offline
      PJ Arends
      wrote on last edited by
      #2

      Chris Losinger wrote:

      since cc will be implicitly cast into a REALLY BIG unsigned integer

      hmmm, I thought it would be the other way around: uCPP would be cast to a signed integer. But it would not be the first time I was wrong. I do have a question about the performace of the code you supplied. Are you not taking a major performance hit by declaring double k inside the loop? Would it not be better to have declared k outside the loop, the same place as you declared v and s?


      You may be right
      I may be crazy
      -- Billy Joel --

      Within you lies the power for good, use it!!!

      Within you lies the power for good; Use it!

      C G 2 Replies Last reply
      0
      • PJ ArendsP PJ Arends

        Chris Losinger wrote:

        since cc will be implicitly cast into a REALLY BIG unsigned integer

        hmmm, I thought it would be the other way around: uCPP would be cast to a signed integer. But it would not be the first time I was wrong. I do have a question about the performace of the code you supplied. Are you not taking a major performance hit by declaring double k inside the loop? Would it not be better to have declared k outside the loop, the same place as you declared v and s?


        You may be right
        I may be crazy
        -- Billy Joel --

        Within you lies the power for good, use it!!!

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

        PJ Arends wrote:

        hmmm, I thought it would be the other way around

        that's what i thought, too. now i'm trying to find all the other places i might have made a similar mistake.

        PJ Arends wrote:

        Are you not taking a major performance hit by declaring double k inside the loop?

        the compiler is smart enough to optimize that away. in the final _asm, it just grabs the data directly from the kernel array and stuffs it into the FP registers as part of the calculation - there's no storage or initialization for anything like 'k' at all.

        image processing | blogging

        1 Reply Last reply
        0
        • C Chris Losinger

          i found this one a couple of days ago. it's the inner loop in a Gaussian blur. it's running a kernel over a rectangular section of pixels...

          double v = 0, s = 0;

          for (int cc=start;cc < stop;cc++)
          {
          double k = kernel[center+cc];
          v += pArray[cc * uCPP] * k;
          s += k;
          }

          uCPP is unsigned. start can be negative. and when start is negative, cc * uCPP is probably going to give an integer overflow, since cc will be implicitly cast into a REALLY BIG unsigned integer... and then you'll get an access violation, since pArray really isn't that big. oddly, it took an x64 build for this to give an A.V. - it worked without crashing (somehow) on all the Win32 builds we had. the fix, of course, is: cc * (int)uCPP alas.

          image processing | blogging

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

          This is getting into the deepest, darkest depths of the C spec, but doesn't integral promotion go the other way? unsigned is converted to signed when the other operand is signed (and there is no built-in type that can express both operands without data loss)? Even if cc*uCPP ended up being a large unsigned value, an array index can be negative, so the large unsigned value would be interpreted as a small negative value. I bet you saw it crash on x64 due to the quantities being extended to 64 bit longs (the next largest type that can express both operands) and not overflowing, so pArray[cc*uCPP] really was indexing far off the end of the array.

          --Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ

          C 1 Reply Last reply
          0
          • M Michael Dunn

            This is getting into the deepest, darkest depths of the C spec, but doesn't integral promotion go the other way? unsigned is converted to signed when the other operand is signed (and there is no built-in type that can express both operands without data loss)? Even if cc*uCPP ended up being a large unsigned value, an array index can be negative, so the large unsigned value would be interpreted as a small negative value. I bet you saw it crash on x64 due to the quantities being extended to 64 bit longs (the next largest type that can express both operands) and not overflowing, so pArray[cc*uCPP] really was indexing far off the end of the array.

            --Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ

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

            Michael Dunn wrote:

            I bet you saw it crash on x64 due to the quantities being extended to 64 bit longs (the next largest type that can express both operands) and not overflowing

            yeah, that makes sense. i can't imagine where else this kind of thing is going to pop up. ugh.

            image processing | blogging

            1 Reply Last reply
            0
            • C Chris Losinger

              i found this one a couple of days ago. it's the inner loop in a Gaussian blur. it's running a kernel over a rectangular section of pixels...

              double v = 0, s = 0;

              for (int cc=start;cc < stop;cc++)
              {
              double k = kernel[center+cc];
              v += pArray[cc * uCPP] * k;
              s += k;
              }

              uCPP is unsigned. start can be negative. and when start is negative, cc * uCPP is probably going to give an integer overflow, since cc will be implicitly cast into a REALLY BIG unsigned integer... and then you'll get an access violation, since pArray really isn't that big. oddly, it took an x64 build for this to give an A.V. - it worked without crashing (somehow) on all the Win32 builds we had. the fix, of course, is: cc * (int)uCPP alas.

              image processing | blogging

              D Offline
              D Offline
              Dan McCormick
              wrote on last edited by
              #6

              For arithmetic expressions of the form:    <signed> <op> <unsigned> or    <unsigned> <op> <signed> C/C++ will promote the <signed> value to <unsigned>. The resulting expression 'signedness' will be <unsigned>. Details available here[^]. Later, Dan

              Be clear about the difference between your role as a programmer and as a tester. The tester in you must be suspicious, uncompromising, hostile, and compulsively obsessed with destroying, utterly destroying, the programmer's software. ----- Boris Beizer

              C 1 Reply Last reply
              0
              • D Dan McCormick

                For arithmetic expressions of the form:    <signed> <op> <unsigned> or    <unsigned> <op> <signed> C/C++ will promote the <signed> value to <unsigned>. The resulting expression 'signedness' will be <unsigned>. Details available here[^]. Later, Dan

                Be clear about the difference between your role as a programmer and as a tester. The tester in you must be suspicious, uncompromising, hostile, and compulsively obsessed with destroying, utterly destroying, the programmer's software. ----- Boris Beizer

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

                i wish the compiler would warn about this one. PCLint doesn't seem to care about it, either (at least not on their interactive demo page).

                image processing | blogging

                R 1 Reply Last reply
                0
                • C Chris Losinger

                  i wish the compiler would warn about this one. PCLint doesn't seem to care about it, either (at least not on their interactive demo page).

                  image processing | blogging

                  R Offline
                  R Offline
                  Rama Krishna Vavilala
                  wrote on last edited by
                  #8

                  Some of this stuff is caught when you set the detect 64 bit portability issues.


                  Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -Brian Kernighan

                  C 1 Reply Last reply
                  0
                  • R Rama Krishna Vavilala

                    Some of this stuff is caught when you set the detect 64 bit portability issues.


                    Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -Brian Kernighan

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

                    yeah, i turned that on, and it found quite a lot of things. not this one, though :(

                    image processing | blogging

                    1 Reply Last reply
                    0
                    • PJ ArendsP PJ Arends

                      Chris Losinger wrote:

                      since cc will be implicitly cast into a REALLY BIG unsigned integer

                      hmmm, I thought it would be the other way around: uCPP would be cast to a signed integer. But it would not be the first time I was wrong. I do have a question about the performace of the code you supplied. Are you not taking a major performance hit by declaring double k inside the loop? Would it not be better to have declared k outside the loop, the same place as you declared v and s?


                      You may be right
                      I may be crazy
                      -- Billy Joel --

                      Within you lies the power for good, use it!!!

                      G Offline
                      G Offline
                      Guffa
                      wrote on last edited by
                      #10

                      PJ Arends wrote:

                      I do have a question about the performace of the code you supplied. Are you not taking a major performance hit by declaring double k inside the loop? Would it not be better to have declared k outside the loop, the same place as you declared v and s?

                      Where you declare a variable only decides it's scope, it doesn't change when it's allocated. All variables that are declared anywhere in a method are allocated when the method is called. The stack pointer is moved to create the neccesary space on the stack for all the variables.

                      --- b { font-weight: normal; }

                      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