How to make sure that different dynamic memory is allocated to the same pointer when using while loop?

Pages: 12
Aug 3, 2021 at 8:07am
@helios, nice catch.
@ganado, by "not working" i meant the program weren't getting desired output from clang.
Aug 3, 2021 at 12:18pm
by "not working" i meant the program weren't getting desired output from clang.
for future reference, that didn't disambiguate anything. But helios was able to figure it out, so I guess this is moot.
Last edited on Aug 3, 2021 at 1:49pm
Aug 3, 2021 at 3:23pm
@ganado, what are you confused about. i said plain english.
Aug 4, 2021 at 11:02am
We don't know what your "desired output" is, so we still have no useful information about your problem. What output are you getting, and how does it differ from what you desire?
Last edited on Aug 4, 2021 at 11:03am
Aug 5, 2021 at 9:58am
@guys, i am really surprised at you that you don't understand simple english. by 'works' i meant it solves what op want(i.e. p gets different location each time) and by 'not working in clang' i meant from clang p get same location each time.
Aug 5, 2021 at 10:28am
Computers do not understand "simple english". If something can be misinterpreted, it will.
As humans (as in "not a lawyer") we do not like to have to interpret any more than the compiler does.
Aug 5, 2021 at 2:07pm
The operating environment is free to give you any legal address that isn't already allocated, so:
1
2
3
int *p = new int;  // It picks some address to give you, and marks it as allocated.
delete p;          // It marks the address as unallocated
p = new int;       // It can give you any unallocated address, including the one you just deleted. 


The point is that when you delete a pointer, you're saying "I don't need what was there anymore. You can return this to the pool of unallocated memory and allocate it again if needed."

This behavior (reusing the pointer) is actually a feature, not a bug. Consider:
1
2
3
4
5
int *p = new int;
for (size_t i = 0; i < 100'000'000'000; ++i) {
    delete p;
    p = new int;
} 

Do you really want the system try to allocate 100 billion different integers when you only need one at a time? Wouldn't you be upset when it says you've run out of memory? I know I would.

Hope this helps.
Aug 5, 2021 at 4:02pm
>
1
2
3
4
5
int *p = new int;
for (size_t i = 0; i < 100'000'000'000; ++i) {
    delete p;
    p = new int;
}  
Do you really want the system try to allocate 100 billion different integers when you only need one at a time?


> it doesn't matter what i want. its up-to compiler. if you read my first comment(the first example program) you will see that clang requests only once for p, and uses the address 5 times (it does't release the memory until last loop). but gcc actually requests 5 times and releases 5 times for p.
Aug 5, 2021 at 4:30pm
clang requests only once

How do you know this? All you do know is each memory allocation is reusing previously freed memory. Reusing the same memory with each repeated request.

It could be argued Clang is more efficient with repeated allocation/freeing of heap memory. Reusing the same memory block instead of grabbing a different block.

Each compiler's implementation is free to organize how operations are done, as long as the standard isn't violated. Does the standard mandate each heap memory allocation MUST be a block that has not been used before in the program, can't reuse a block previously used and freed?
Last edited on Aug 5, 2021 at 4:42pm
Aug 5, 2021 at 5:42pm
>
Does the standard mandate each heap memory allocation MUST be a block that has not been used before in the program, can't reuse a block previously used and freed?

>logically they cant mandate that.
Aug 5, 2021 at 6:55pm
The standard COULD mandate it, but it isn't likely it ever will. "Logic" doesn't mean diddly.

You avoided the issue, you expect behavior that is neither part of the standard and is left to each compiler's implementation for how heap memory allocations happen.

You expecting a certain way doesn't mean a compiler that does it differently is wrong. It is your expectation that is faulty.
Aug 5, 2021 at 7:44pm
>
You avoided the issue, you expect behavior that is neither part of the standard and is left to each compiler's implementation for how heap memory allocations happen.

You expecting a certain way doesn't mean a compiler that does it differently is wrong. It is your expectation that is faulty.

> you got me wrong.

>
The standard COULD mandate it

> if stroustrup & compilers forced it at the beginning & asserted it as fixed feature, C++ would have died before becoming popular.
Aug 6, 2021 at 5:17am
> The standard COULD mandate it

The allocation/deallocation functions defined by the standard library are replaceable; the standard allows a program to implement its own functions. https://eel.is/c++draft/new.delete.single#2

A trivialised example (it need not result in the 'expected' behaviour; the standard allows allocation elision for new expressions, even when there is a program-defined replacement function):

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
35
36
37
38
#include <new>
#include <cstddef>
#include <iostream>
#include <cstdint>

[[nodiscard]] void* operator new( std::size_t sz, const std::nothrow_t& ) noexcept
{
    static constexpr std::size_t MAX_ALLOCS = 1024 ;
    static constexpr std::size_t MAX_ALLOC_SZ = 2048 ;

    struct alignas(std::max_align_t) block { char buffer[MAX_ALLOC_SZ] {} ; };
    static block free_store[MAX_ALLOCS] {} ;
    static std::size_t num_allocs = 0 ;

    if( num_allocs < MAX_ALLOCS && sz <= MAX_ALLOC_SZ ) return free_store + num_allocs++ ;
    else return nullptr ;
}

[[nodiscard]] void* operator new( std::size_t sz )
{
    void* p = ::operator new( sz, std::nothrow ) ;
    if(p) return p ;
    if( auto nh = std::get_new_handler() ) { nh() ; return ::operator new(sz) ; }
    throw std::bad_alloc() ;
}

void operator delete( void* ) noexcept { /* do nothing */ }
void operator delete( void*, std::size_t ) noexcept { /* do nothing */ }

int main()
{
    for( int i = 0 ; i < 10 ; ++i )
    {
        auto p = new int{ 100 + i + i*i + i*i*i } ;
        std::cout << i << ". int " << *p << " at " << p << " (" << reinterpret_cast<std::uintptr_t>(p) << ")\n" ;
        delete p ;
    }
}

http://coliru.stacked-crooked.com/a/f4d3dedc931bdc5f


> This behaviour (reusing the pointer) is actually a feature, not a bug

It is a feature that improves cache/memory performance, and possibly makes the allocation more efficient.

Not reusing the most recently deallocated storage, if another is available, would be a feature that could be useful in debug builds; particularly in programs that rely on C-style memory management. Ideally, trash the contents of the deallocated storage before returning it to the free store.
Sep 11, 2021 at 9:21pm
it has been a while, but i just found a new idea:
first, your program gets a big area of memory (i.e. 10MB or 100MB whatever) from os.
then you use random to locate the variable in that memory. the bigger the memory, the less chance of getting same location for your variable in next loop.
Sep 11, 2021 at 11:09pm
That's so dumb.

If you had 2^128 bytes of memory, you could use Rjindael in CTR mode and you'd be guaranteed not to get the same address twice until all addresses had been exhausted. The problem becomes a bit more difficult if your objects are not all 1 byte long.

EDIT: Come to think of it, if you're preallocating a continuous region then you have complete control over it. You can suballocate within that region by simply incrementing a pointer.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Allocator{
    std::unique_ptr<char[]> buffer;
    size_t size;
    char *next;
public:
    Allocator(size_t size){
        this->size = size;
        this->buffer.reset(new char[size]);
        this->start = this->next.get();
    }
    void *allocate(size_t bytes){
        auto ret = this->next;
        if (this->next + bytes - this->buffer.get() > this->size)
            throw std::bad_alloc();
        this->next += bytes;
        return ret;
    }
}
Last edited on Sep 11, 2021 at 11:29pm
Sep 12, 2021 at 1:49pm
>
That's so dumb

not really. that's part of design. imagine you won lottery. that doesn't disqualify you from winning next year. at the same time organizers not giving money to same person every year (it does not violate ops requirement(2nd line of his first post)).
Sep 12, 2021 at 10:20pm
Yeah, "lottery". It's like being given hotel keys at random. Maybe you'll get a room for yourself, maybe you'll get to figure out how to share a bed with a complete stranger.
Sep 13, 2021 at 2:58pm
Just wanted to share with everyone this very mature PM I just got from anup30 in reply to my previous post:
gladly, if the stranger is your gf.
Congratulations, friend. You just got added to my ignore list. I hope what little amusement you got out of it was worth it.
Sep 13, 2021 at 8:34pm
you started the slang.
Topic archived. No new replies allowed.
Pages: 12