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

Pages: 12
@helios, nice catch.
@ganado, by "not working" i meant the program weren't getting desired output from clang.
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
@ganado, what are you confused about. i said plain english.
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
@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.
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.
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.
>
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.
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
>
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.
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.
>
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.
> 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.
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.
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
>
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)).
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.
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.
you started the slang.
Topic archived. No new replies allowed.
Pages: 12