피호출함수에서 동적으로 할당된 메모리 자동으로 해제할 수 없을까요?

dltkddyd의 이미지

char* allf() {
	char* chs=new char[10];
	return chs;
}
 
int main() {
	allf();
	return 0;
}

allf 함수는 메모리를 동적으로 할당하고 그 메모리를 반환합니다. 이 메모리가 반환된 직후에 해제되도록 할 수 있을까요? 물론 다음과 같이 main 에서

char* ch=allf();

언급하고

delete[] ch;

하면 이를 해제할 수 있습니다만, 그렇게 하지 않고 함수가 호출부로 다시 돌아온 직후에 바로 메모리 해제되도록 할 수 있을까요? 메모리는 반환되면서 말이죠.

oosap의 이미지

C++ 에서는 다양한 스마트 포인터들이 이런 목적으로 사용됩니다.

http://www.relisoft.com/resource/resmain.html

위에 설명된 내용은 오래된 내용이라서 C++11 부터는 deprecated 된 std::auto_ptr 에 대해서도 설명하고 있는데요, 부스트의 스마트 포인터 라이브러리를 공부해보세요..

http://www.boost.org/doc/libs/1_53_0/libs/smart_ptr/smart_ptr.htm

이것들 중 일부는 C++11 STL 에도 들어가 있습니다.

http://en.cppreference.com/w/cpp/memory

Thanks for being one of those who care for people and mankind.
I'd like to be one of those as well.

dltkddyd의 이미지

원문 해석하려면 조금 시간이 걸리겠지만, 읽어보면 실마리가 잡힐 것 같습니다. 감사합니다.

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

oosap의 이미지

C++ 에서 메모리 릭 혹은 메모리 이중 해제와 같은 성가신 문제를 해결하는 방법으로 이 글에서는 리소스 관리의 한 방법론을 설명한다.

이는 리소스 관리의 한가지 전제 , 그리고 리소스 획득의 한가지 원칙 으로 설명할 수 있다.

리소스 관리의 한가지 전제 : 모든 리소스가 자신의 소유자를 갖도록 해야 한다.
리소스 획득의 한가지 원칙 : 리소스의 할당(획득)은 생성자에서 리소스의 해제는 그에 상응하는 소멸자에서 수행해야 한다.

리소스는 자동 리소스(언어적 특징으로 리소스 관리가 자동으로 이루어짐. 자동변수)와 동적 리소스(new, delete 등, 크리티컬 섹션, 파일 등 처럼 명시적으로 할당 및 해제를 수행해야 함)가 있는데 리소스 관리의 관심사항은 동적 리소스이다. 요약해서 얘기하면 이 글의 방법론에서는 동적리소스도 std::auto_ptr 을 활용해서 자동리소스처럼 취급하도록 한다. 소유권을 가지는 강한 스마트 포인터와 소유권을 갖지 않는 약한 포인터의 개념이 도입되며 소유자가 두 개 이상 되어야만 하는 경우 사용할 수 있는 래퍼런스 카운트 기반의 스마트 포인터도 설명한다. 이를 위한 구체적인 가이드라인을 제시하며 소스코드도 제공한다.

글을 읽으면서 new를 항상 생성자가 불리는 곳에서 매개변수로 리소스를 할당하는데 사용하는 모습을 보면서 디자인패턴의 팩토리 패턴도 생각해보았다. 하지만 팩토리 패턴은 알고리즘과 구체적 구상클래스의 핸들링을 분리하는데 의가 있는 것으로 이 글의 리소스 관리의 방법론과는 차원이 다른 범주의 이야기이다.

글의 마지막에서 소개하는 사례가 아마도 이 글의 핵심적인 내용일 것이다. auto_ptr과 auto_vector를 사용해서 동적 리소스를 자동리소스화 했다. 이 때 사용된 auto_vector는 Permutation Vector 라는 것으로 소유권을 가지는 강한 스마트포인터(auto_ptr)을 퍼뮤테이션 벡터 한군데에 모아두고 핵심 알고리즘의 수행은 소유권을 갖지 않는 약한 포인터를 통해 표준 컨테이너 상에서 수행하고 있다.

질문 : 강한 (스마트) 포인터, 약한 포인터, 퍼뮤테이션 벡터 등의 용어는 어떤 과목에서 정의한 것인가?

이 글은 제가 이 포스트를 읽고 아주 간단히 정리해보았던 글입니다. 번역을 시도했었다가 양이 너무 많고 귀차니즘으로 포기했더랬습니다. 그런데 내용이 저자가 구현한 스마트 포인터에 대한 소개가 주를 이룹니다. 개발자가 직접 스마트 포인터를 만들어 쓰는 것도 실력있는 프로그래머라면 괜찮겠지만, 저같은 경우는 아예 안하는게 낫겠더라구요. 다행히 표준 라이브러리에 좋은 스마트 포인터가 있으니 그걸 쓰는게 머릿속 편하게 살 수 있는 방법이다 결론내렸습니다.

그러니 이 내용을 다 읽지는 않으셔도 아이디어만 잡으셔도 될 것같습니다. 제가 여기 적어놓은 정도만 보시고 스마트 포인터에 대한 다양한 글들을 접해보시는 걸 권해드립니다.
제가 질문으로 적어놨던 것들중 강하고 약한 스마트 포인터와 같은 개념은 boost 나 C++11 의 스마트 포인터를 공부해보면 잘 알 수 있더군요. 안드로이드 프레임워크 소스를 보면 이 부분이 흔하게 나오기도 합니다.
퍼뮤테이션 벡터와 같은 개념은 다른 곳에서 보지 못했던 것입니다. 사실 저도 이 내용은 이해를 못합니다.

제가 글을 너무 길게 썼습니다.

Thanks for being one of those who care for people and mankind.
I'd like to be one of those as well.

익명 사용자의 이미지

의도가 무엇인지요?
리턴 후에 바로 반환한다면 호출 함수에서 포인터를 참조하지 않겠다는 뜻 아닌가요?
리턴 후에 바로 반환하는 것과 그냥 피호출함수에서 반환하는 것의 차이가 없는 것같습니다만...

익명 사용자의 이미지

+1

익명 사용자의 이미지

Allocate it in the stack space with a dynamic size array, and return it to the caller. You should use it with a caution -- the stack allocated space is valid only before you call another function.
As long as you understand it, and use it with a caution, I think it is fine.

익명 사용자의 이미지

>> the stack allocated space is valid only before you call another function

그런 보장 없습니다.
반환 이후에 다른 함수를 호출하지 않더라도 그 스택 영역에 접근하는 것은 불법적인 행동입니다.

익명 사용자의 이미지

Thanks for letting me know, but isn't it valid if you do not allocate anything in the stack after the function call? (and before another function call)

익명 사용자의 이미지

http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope

다시 말씀드리지만 그 메모리 영역에 무엇이 있을지 아무 것도 보장되지 않습니다.
특정 OS, 특정 컴파일러의 특정 버젼에서 그 메모리에 성공적으로 접근했다고 해서 그게 항상 해도 되는 일인 것은 아닙니다.

sunyzero의 이미지

VLA를 쓰면 될 것 같습니다.

함수 스코프를 넘어가지 않는 변수라면 스택을 쓰는 것이 훨씬 편합니다.

========================================
* The truth will set you free.

익명 사용자의 이미지

그렇기는 하지만 스택 크기에 제한이 있기 때문에 큰 메모리를 잡을 수는 없습니다.
뭐 스택 크기를 늘리면 되겠지만, 어느정도의 메모리를 사용할 지 미리 짐작하기 어려울때는 그것도 어렵고
사실 사용자에게 스택 크기를 늘리라고 요구하는 것도 좋은 생각은 아닐 듯 합니다.

익명 사용자의 이미지

굳이 그런 구조를 가져야 한다면 적당한 스마트 포인터를 사용하면 됩니다.

#include <memory>
#include <iostream>
 
struct foo {
  foo() { std::cout << "Created.\n"; }
  ~foo() { std::cout << "Deleted.\n"; }
  void do_something() { std::cout << "Do something...\n"; }
};
 
std::unique_ptr<foo> func() {
  std::unique_ptr<foo> a(new foo);
  return a;
}
 
int main() {
  std::unique_ptr<foo> a = func();
  a->do_something();
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.