0
int main()
{
    int *array = new int; //Should provide space to store only one integer right?
    
    for(int i =0; i < 10; i++) 
    {
        cout << "Assigning" << i << "th value\n";
        array[i] = i + 1;
    }
    

    for(int i = 0; i < 10; i++)
        cout << array[i] << '\t';

    delete array;
    cout << '\n';
    return 0;
}

Output

Assigning0th value
Assigning1th value
Assigning2th value
Assigning3th value
Assigning4th value
Assigning5th value
Assigning6th value
Assigning7th value
Assigning8th value
Assigning9th value
1       2       3       4       5       6       7       8       154274097       154405171

I know pointer size on my system is 8 bytes, checked with sizeof(int*) and integers take 4 bytes. I want to know how many chunks of memory in heap or free store (like literally boxes they use to teach students) does int* array = new int created, because books say I can store just one integer in it; to store more(like 10 ints) I need to do int* array = new int[10]. So how does this memory location pointed to by array can store 8 integers instead of one. Please note, I ran for loop 10 times as shown. Please tell me why are there just 2 garbage values, instead of 9 (since new should only allocate one integer worth space). Using Ubuntu with g++ 9.3.0.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • 4
    You're allocating a 0-element array and then acting like it has 10 elements... no bueno. – Shawn Jul 15 '20 at 14:02
  • 4
    You are taking the `sizeof` a pointer, not the array, probably on a 64-bit system so the pointers are 8 bytes. – Mansoor Jul 15 '20 at 14:03
  • 1
    Two words: [nasal demons](http://catb.org/jargon/html/N/nasal-demons.html) (or [Undefined Behaviour](https://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviours-that-a-c-programmer-should-know-a)). You have enough space for exactly 0 integers, but you read and write 10. Anything can happen. – Yksisarvinen Jul 15 '20 at 14:04
  • 2
    Looks like it's legal to use `new[]` to allocate a 0-element array, but the only thing you can really do with the returned pointer is `delete[]` it. – Shawn Jul 15 '20 at 14:05
  • For your platform: `sizeof(int)` is indeed 4 but `array` is not an `int` but an `int*`. And `sizeof(int*)` is 8 (for your system). – Fareanor Jul 15 '20 at 14:13
  • C++ does not care if you overwrite a buffer. That is exactly how buffer overrun security holes are exploited -- code similar to what you wrote. It's your responsibility to not overwrite the buffer -- that's how C++ works. – PaulMcKenzie Jul 15 '20 at 14:14
  • @Shawn You also can copy the pointer ^^. I am curious if it causes memory leaks if you do note delete such pointers. or if you even get different addresses for multiple zero length arrays – vlad_tepesch Jul 15 '20 at 14:15
  • @vlad_tepesch -- It is a memory leak. Memory may have been allocated to maintain the heap itself, or in a debug environment, memory allocated for the guard bytes that check for memory overwrites. – PaulMcKenzie Jul 15 '20 at 14:16
  • As for terminology, there is no _`new` operator_ involved in your code. There is _`new` expression_ instead. These are two different things. – Daniel Langr Jul 15 '20 at 14:23
  • @vlad_tepesch I assume it's like `malloc(0)` where whether it returns a non-null pointer or not is implementation defined. – Shawn Jul 15 '20 at 14:23
  • @PaulMcKenzie you are true, if there actually is any allocation happening. My thought was, that there is nothing you can really do with such an array the allocator may just give you some bogus pointer – vlad_tepesch Jul 15 '20 at 14:26
  • @vlad_tepesch -- Yes, however the heap manager has to keep track of the bogus pointer in some way, otherwise the `delete []` call will fail on the pointer. That's why there is something being done behind the curtain, even for a 0-size allocation. – PaulMcKenzie Jul 15 '20 at 14:28
  • @PaulMcKenzie i do not see any reason why this could not be optimized to a simple `intptr_t` global in the `new[]` and `delete[]` implementation. init that global with a number outside the normal heap address space and on zero size new return that number as pointer and increment it. `delete []`just ignores pointer in that range. The question is just how important is that use case and is it important eough to implement and maintain such a feature – vlad_tepesch Jul 15 '20 at 14:37
  • To answer your follow-up question: It seems that you don't understand the nature of [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior). If your program invokes any kind of undefined behavior (for example by accessing an array out of bounds), the behavior of your entire program is undefined. In that respect, all 10 values of your program are garbage values. You were just lucky that most of them appear to be correct. On a different compiler or with different compiler settings, this may change. – Andreas Wenzel Jul 15 '20 at 18:54
  • If you really want to know exactly why **on your specific compiler** the first 8 values appear to be correct and why 2 are wrong, you will have to take a look at the [assembly code](https://en.wikipedia.org/wiki/Assembly_language) that your compiler emits. However, such details are normally not interesting to a programmer, because these details can change according to compiler version, operating system, compiler settings, etc. Therefore, as a programmer, you should only care about not invoking undefined behavior in the first place, because only then are you always safe. – Andreas Wenzel Jul 15 '20 at 19:29

1 Answers1

4
int *array = new int; //Should provide space to store only one integer right?

Allocates a single int not an array.

for(int i =0; i < 10; i++) 
{
    cout << "Assigning" << i << "th value\n";
    array[i] = i + 1;
}

Since there is no array but only a single element any access beyond the first (array[0]) array elements causes undefined behavior. Any action, even formatting your hard drive, would be a valid program behavior.

Edit:
adapted to nearly completely rewritten question

vlad_tepesch
  • 6,681
  • 1
  • 38
  • 80
  • It appears that the OP has edited his question in such a way that most of your answer has been invalidated. :-( – Andreas Wenzel Jul 15 '20 at 18:34
  • I have now edited the question in order to restore the original question and have marked the new question as a follow-up question. Now your answer is no longer invalidated. – Andreas Wenzel Jul 15 '20 at 18:39
  • I have decided to revert my changes to the question, because I am not sure if my changes were appropriate. Even if the OP's changes invalidated half of your answer, one could argue that the quality of the question has improved, because it focusses on one issue now and it also provides a better demonstration of the issue. Therefore, it may be more appropriate for your answer to be adapted to the updated question, even if that means that your answer will be significantly shorter. – Andreas Wenzel Jul 15 '20 at 19:07
  • @AndreasWenzel i dapted the answer. I also thought about reverting the question with the comment to create a new question – vlad_tepesch Jul 15 '20 at 19:16
  • I don't think asking the OP to post it as a new question would have been appropriate, because that would have created another duplicate of this 11 year old question: [Accessing an array out of bounds gives no error, why?](https://stackoverflow.com/questions/1239938/accessing-an-array-out-of-bounds-gives-no-error-why) – Andreas Wenzel Jul 15 '20 at 19:35