problem from tutorial

Pages: 1234
Munching popcorn too?
Wrong, I tried 1,000,000,000 and it gives the "Error: memory could not be allocated" message. Same as in VC++ and ideone.
Well does not for us. i'll take a picture and prove it. BRB

EDIT UPDATE : Uploading a video to youtube instead. I'll post the link here once its done.
Last edited on
What are we now disagreeing about now? If 1,000,000,000 crash or not is not something to argue about. It will depend on your system and not so much on the compiler.
Munching popcorn too?

Oh yes, although I had to resort to peanuts.

What are we now disagreeing about now? If 1,000,000,000 crash or not is not something to argue about. It will depend on your system and not so much on the compiler.

It'll crash reliably with a 32-bit program, if int is 4 bytes (both happen to be the case for the oh-so-much-cited "MinGW that comes with Code::Blocks"). 1,000,000,000 is within int's range, but the following allocation would be too big to fit into the address space.
@WinwordExonar - what will happen if we perform the check with the star - then set the first element of the array to zero via p[0] = 0, and then reperform the test again.

Basically:

1
2
3
4
5
6
7
8
9
10
11
12
   if (*p == 0)
   {
       throw ...
   }

   p[0] = 0;         .. just setting 1st element of array to zero

   if (*p == 0)
   {
       throw ...
   }


In my mind this code will generate an error on the 2nd time once the 2nd test is hit.

What happens on your system?

If it also generates an error on the 2nd check then this can't be right as the 1st check has already verified that the memory for p was allocated.
@SIK Nice example, that is basically all I'm trying to get across to WinwordExonar. I may not be the best at explaining myself.
@ Arthar - Your correct in what your saying. The INT has limits. I get that and I can see those limits if I did a straight up int i = INT_MAX limits . But.. whats happening here is not what the others are saying and this is where the misunderstanding is at. Its not that we are trying to argue, its trying to get the other person to see what the other one is saying. This whole thread is basically trying to get the other to see the point of view of the other person. What your saying Arthar is what was said earlier which is why I pointed out the INT_MAX earlier to show that I do know the limits. And if you check it out, beings that its a 4 Byte limit you should not be able to type in over 4.2 billion. But we can . It errors out to a weird scrolling effect which is what the OP is saying. I'll be able to show you what I mean once this youtube video is finished uploading. And we can type out over 4.5 billion and still do not get it to come up saying the error message. It scrolls instead.

@SIK Yes that worked the same way as * does. There was no difference if I used a [0] or a * symbol. Thank you.
Last edited on
@naraku9333


@SIK Nice example, that is basically all I'm trying to get across to WinwordExonar. I may not be the best at explaining myself.


Apparently, I'm not as good as you think :)

*munch*

Popcorn anyone?
Okay well, to summarize what has pretty much already been said anyway:
cin >> i; fails if the number entered is too large (here, that means >2,147,483,647=INT_MAX).
You can test whether that has happened by testing the fail bit ( if (cin.fail()) or if (!cin) as already shown by Peter). Now, if it fails, i will not be changed. i was never initialized, so it still has the same indeterminate value as before. That can be anything from 0 to some (absolute) large number. Depending on that number, the allocation will either succeed or fail. If it fails, the nothrow variant of new[] will return 0 and you can test that with if (p==0)...
If you tried if (*p==0) in the failure case, you'd be dereferencing a null pointer and the application would crash, obviously.

And that's all there is to it. Has nothing to do with compilers or anything else.
Oh oh!

My Code::Blocks 10.05 closes the console window immediately after the program ends when in debug mode.

Should that be the whole reason for.... *sigh*
Last edited on
@SIK Yes that worked the same way as * does. There was no difference if I used a [0] or a * symbol. Thank you.


I think you misunderstood me - try the following as is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>


using namespace std;



int main()
{
   int count = 3;    

   int * p = new int[count];

   if (*p == 0)
   {
      cout << "int array for p was not allocated" << endl;
      return -1;
   }

   p[0] = 0;      // just merely setting 1st element to zero

   if (*p == 0)
   {
      cout << "2nd check: int array for p was not allocated???" << endl;
      cout << "How can this be - it was allocated in check1 and" << endl;
      cout << "all we did was set the 1st item to zero" << endl;
      cout << "this should not cause it to become deallocated" << endl;
      cout << "Please Explain this!!!" << endl;
      return -2;
   }

   cout << "array for p was successfully allocated - we can now add all elements" << endl;
   return 0;
}


If this is run on any compiler it will always produce the result:

2nd check: int array for p was not allocated???
How can this be - it was allocated in check1 and
all we did was set the 1st item to zero
this should not cause it to become deallocated
Please Explain this!!!


If you change the check from [if (*p == 0)] to [if (p == 0)] for both checks then the program will output:


array for p was successfully allocated - we can now add all elements


This is the output we expect from the program given above - hence the check without the * is correct - the fact that the cases provided succeeded is only incidental to fact that p[0] at the time you referenced it had some garbage value in (not zero) and memroy access was illegal but not severe enough to crash progam.

I remember a maths class at school, sometime during the 90s. In that class, the teacher told us that 0.9 recurring has the same value as 1, he was right, but I just plain refused to believe it. I got into a big argument, and he must have proved it to me by at least 3 different methods, but I just couldn't accept it. It wouldn't have mattered how logical or sensible his argument, because at that point in time, my brain just couldn't accept what was being said to me. The only way for me to come around to the idea was to go away for a few weeks and try things for myself.

Take from that story what you will...
Ok, here is the video :

http://www.youtube.com/watch?v=vOsLQ-d-XvA

Ok now i'll break this down so you can understand what its doing in the code if I do not put the * symbol in there.

1
2
3
4
5
6
7
8
9
10
11
// rememb.o.matic
#include <iostream>
#include <new>
using namespace std;

int main ()
{
  int i,n;
  int * p;
  cout << "How many numbers would you like to type? ";
  cin >> i;


So if you type in any number below 4.2 billion it will not error out. However above it say 4.5 million and it will IF you add in the *. But without it, it will not throw an exception. So what its doing is bypassing this :

1
2
3
  p = new (nothrow) int[i];
  if (p == 0)
    cout << "Error: memory could not be allocated";


and goes on to the ELSE statement instead. But.. The reason ? well it thinks that p is an integer and not a pointer at this point. The * tells the compiler that it IS a pointer, whether this is right or wrong this is how MinGW is acting.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  else
  {

    for (n=0; n<i; n++)
    {
      cout << "Enter number: ";
      cin >> p[n];
    }
    cout << "You have entered: ";
    for (n=0; n<i; n++)
      cout << p[n] << ", ";
    delete[] p;
  }
  return 0;
}


So it goes into a loop at this point and just repeats itself counting the integer i down to the end of its number count that you typed in.

Now this page on this forum explains it better then I can because people get Pointers confused with Arrays.

http://cplusplus.com/forum/articles/10/

Its a BIG misunderstand for people who do not know the difference. And so they think Pointers are arrays. BUT.. Arrays have Pointers. Which is also brought out in that thread.

@ SIK - Try this and it will be the same as if you put in the * for both. Change both of those to this and it will work as expected just like the * Symbol does. if (p[0] == 0)


As Cali pointed out, it acts differently on the MinGW and as I am showing you in the video. I also went a step further and tried it as Release and it does the same thing. So this is a compiler issue. Its why in all this past year of my putting * in its place has worked for me while on other compilers I do not need it.

Arthar Says...
Depending on that number, the allocation will either succeed or fail. If it fails, the nothrow variant of new[] will return 0 and you can test that with if (p==0)...
If you tried if (*p==0) in the failure case, you'd be dereferencing a null pointer and the application would crash, obviously.


And see we are seeing the opposite in my video. The * makes sure that is does the job correctly. WHY ? I don't know and that is the problem here. I am wondering if there is a BUG in the debug for MinGW as Cali has pointed out. But its a BIG issue if we are all sitting here arguing about something, and we are all saying same thing but the compiler / Debug shows it different.

@ kev82 -- I love that. Thanks for sharing.

NOTE : I totally understand what Naraku is saying here
asterisk dereferences the pointer to access its value
but this compiler doesn't seem to work right without the * symbol.
Last edited on
I understand pointers and arrays.

I also read the link [http://cplusplus.com/forum/articles/10/]

Just a quote from link:


The handling of arrays as pointers is very crucial to an understanding of C. For example, you can pass an array anywhere a pointer is expected, and vice versa. A function can handle arrays, but define the type it recieves as a pointer. And since arrays are pointers (constant pointers), they are passed call by reference, meaning the array passed will be modified immediately in the calling function.


Also to add comment to article array[0] is not an address, but &array[0] is.

After reading through article I was still not able to try what you said - can you please post code and show clearly what is meant.

Also supply comment on the actual example I posted - did this work exactly as I said it would?
ie, do you agree that in my example the version without the star works correctly?

However above it say 4.5 million and it will IF you add in the *. But without it, it will not throw an exception
Do you mean 4 500 000 000? In that case you will exceed INT_MAX and cin >> i; will fail.
and goes on to the ELSE statement instead. But.. The reason ?
new (nothrow) int[i]; might not fail because we don't know the value of i.
Inside the loop all operations on cin will fail because the failbit has been set when we read in i. That is why we get the spinning loop.
Last edited on
@ SIK -- Try this, you'll see what I mean. This is without the * Symbol. The 4.5 Billion should throw an error and the first if (p == 0) should catch it, but it goes straight through anyways because it doesn't throw an exception error out for the program to catch it. It thinks the p is an integer. Basically its doing the same thing as is in my video.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>

using namespace std;

int main()
{
   int count = 4500000000;

   int * p = new int[count];

   if (p == 0)
   {
      cout << "int array for p was not allocated" << endl;
      return -1;
   }

   p[0] = 0;      // just merely setting 1st element to zero

   if (p == 0)
   {
      cout << "2nd check: int array for p was not allocated???" << endl;
      cout << "How can this be - it was allocated in check1 and" << endl;
      cout << "all we did was set the 1st item to zero" << endl;
      cout << "this should not cause it to become deallocated" << endl;
      cout << "Please Explain this!!!" << endl;
      return -2;
   }

   cout << "array for p was successfully allocated - we can now add all elements" << endl;
   return 0;
}


You put in the * Symbol and it works just fine like its supposed too. However, why it throws out an exception on the 2nd one if you use only one or the other is because your trying to toggle the pointer to be a non array symbol. You cannot do that since pointers can not be arrays. Arrays have constant pointers, but not the other way around. Comment out this line return -1; and you'll see what I mean. Experiment.
I remember Spoonlicker. As I recall, Spoonlicker made it very clear what teenage girls do. It was a FACT. Which was nice.
spoonlicker!

Argh!

Now that you mentioned him. Yes! You might have nailed it.

Last edited on
Pages: 1234