Dynamic allocation and functions

Aug 3, 2022 at 3:18pm
Consider the sippet below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
char *func(void)
{
    char *str = new char[3];
    str[0] = 'a';
    str[1] = 'b';
    str[2] = '\0';

    return str;
}

int main()
{
    cout << func() << endl;

    return 0;
}


Here I can get the str from func() but I cannot delete it, and if I delete str I wont be able to get str, how to solve this delema)?
Last edited on Aug 3, 2022 at 3:19pm
Aug 3, 2022 at 3:32pm
The function dynamically allocated the array and returns the pointer to the caller.

Hence the caller is responsible for delete[]'ing the array when no longer needed, to avoid memory leaks!

Try something like:
1
2
3
4
5
6
7
8
int main()
{
    char *ptr = func();
    cout << ptr << endl;
    delete[] ptr;

    return 0;
}

...or with using std::unique_ptr smart pointers:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
std::unique_ptr<char[]> func(void)
{
    auto str = std::unique_ptr<char[]>(new char[3]); // <-- wrap array pointer in std::unique_ptr
    str[0] = 'a';
    str[1] = 'b';
    str[2] = '\0';
    return str; // <-- this implicitly "moves" the std::unique_ptr to the caller, thus transferring the ownership of the array from this function to the caller
}

int main()
{
    cout << func().get() << endl;  // <-- when the temporary std::unique_ptr object is destroyed, then the wrapped array is delete[]'ed automatically!
    return 0;
}
Last edited on Aug 3, 2022 at 5:59pm
Aug 3, 2022 at 3:54pm
Just sayin', if you're going to using a unique_ptr<array>, you should really just consider using a string or vector. Of course, demonstrating its use for educational purposes like you did is fine, I just personally wouldn't use that in actual code.
Last edited on Aug 3, 2022 at 3:56pm
Aug 3, 2022 at 4:02pm
You need to obtain the address returned by func() in a variable so that it can be used with delete[].

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

auto func(void) {
	return new char[3] {"ab"};
}

int main() {
	const auto f { func() };

	std::cout << f << '\n';
	delete[] f;
}



However, a better way is to use 'smart' pointers then you don't need to bother about delete as this is done automatically when goes out of scope.

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <memory>

auto func(void) {
	return std::unique_ptr<char[]> (new char[3] {"ab"});
}

int main() {
	std::cout << func() << '\n';
}

Aug 3, 2022 at 4:13pm
Just sayin', if you're going to using a unique_ptr<array>, you should really just consider using a string or vector. Of course, demonstrating its use for educational purposes like you did is fine, I just personally wouldn't use that in actual code.


Yeah - but still better than returning a raw pointer and needing delete []...
Aug 3, 2022 at 5:01pm
Smart pointer does the work ++

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

std::unique_ptr<char[]> f(void)
{
    return std::unique_ptr<char[]>(new char[5]{ "test" });
}

int main()
{
    std::cout << f().get() << std::endl;
    return 0;
}
Aug 3, 2022 at 9:31pm
No leaks, no trouble...
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <string>

std::string func()
{
	return "ab";
}

int main()
{
	std::cout << func() << std::endl;
}
Last edited on Aug 3, 2022 at 9:31pm
Aug 4, 2022 at 8:07am
Small point - but stream extraction doesn't require .get() with a smart pointer to access the contents. In the above, f() works fine so no need for f().get()

Aug 4, 2022 at 9:19am
No idea whether this leaks! (One of the problems with auto.)

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>

auto func()
{
	return "ab";
}

int main()
{
	std::cout << func() << '\n';
}
Aug 4, 2022 at 9:55am
There is no dynamic allocation so no leaks.

The return type is simply deduced as const char*.
Aug 4, 2022 at 9:59am
no - no leaks as no dynamic allocation.

However even if the return type of func() is known (const char*) this doesn't give us any info as to where pointer ownership resides. Do we need to delete[] it? In this case no as it wasn't obtained from a new and ownership isn't passed. But if the return address was obtained from a new then yes, we would need to delete[] it as ownership has been 'passed' but this can't be known from just the function return type.

If the ownership of the memory is to be passed, then a return type of std::unique_ptr makes this clear and the caller knows (and also doen't need to do anything about it as delete [] will be automatic when needed.
Last edited on Aug 4, 2022 at 10:11am
Aug 4, 2022 at 10:48am
However even if the return type of func() is known (const char*) this doesn't give us any info as to where pointer ownership resides. Do we need to delete[] it?

That's why in Rust the ownership is explicit and is enforced/checked by the compiler (borrow checker):
https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html
https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html
Last edited on Aug 4, 2022 at 11:07am
Aug 4, 2022 at 4:52pm
I thought rust was 'to degenerate especially from inaction, lack of use, or passage of time'
Aug 4, 2022 at 5:50pm
Rust is a programming language that is supposed to be a "better C++" and replace C/C++ as The Sole Programming language eveh. At least according to Rust advocates and zealots.

I am not of them.

Rust is just the latest "shiny thing." Similar to Java, Rust is a nice idea next-step language that has IMO a niche applicability.

C/C++ are still dominant life forms for creating a wide variety of compiled applications. I don't see C/C++ being replaced any time soon.
Aug 4, 2022 at 6:08pm
Aug 4, 2022 at 7:11pm
Regarding Rust's borrow checker:

Both C++ and Rust support static checking of ownership.

C++'s approach to ownership is based on conventions, and is opt-in. To opt-in you make disciplined use of unique_ptr, value semantics, and RAII in your program.

Rust's approach to ownership is based on the definition of the type system, and is opt-out. To opt-out you put your code in an "unsafe block" which relaxes the type checker.

Rust does have some good ideas here. There's value in getting safety guarantees for free -- even though it's not going to be "free" all the time.

I expect it's already dogma to avoid their unsafe keyword.
Last edited on Aug 4, 2022 at 10:29pm
Aug 6, 2022 at 6:52pm
Thank you all for contributing to this topic, I learn so much from you :)
Topic archived. No new replies allowed.