2012-05-22 2 views
7

C++로 프로젝트를 시작했습니다. 이 언어로 된 메모리 관리는 저에게 새로운 것입니다.C++ 메모리 관리 기법/프랙티스

new()으로 개체를 만든 다음 포인터를 전달하고 작동하는 동안 디버그하는 것이 어려워 사람들이 코드를 보았을 때 나를 재미있게 보았습니다. 나는 그것이 누설되거나 segfault (한 번 고정)되지 않았다는 사실을 아주 자랑스럽게 생각하지만 실제로 많은 노력이 필요했습니다.

list <struct Connection *> users; 

struct Connection * accept_connection (const char *name) { 
    struct Connection * new_node = new Connection(); 
    new_node->_data = ... // whatever, set it up here 
    return new_node; 
} 

struct Connection * new_user = accept_connection (const char *name); 
users.append (new_user); 

그래서이 프로젝트의 다음 버전에 대한 새로운 전략이 있습니다. 지금까지 내가하고있는 일은 new()으로 개체를 만들고 고유 한 정수 ID 번호를 할당하는 것입니다. 그런 다음 ID를 키로 사용하여 해시 테이블에 개체를 저장합니다. 이제 항목은 정수 ID 번호로 저장되고 전달되며 해시 테이블로 이동하면 thing * 또는 NULL 중 하나가 반환됩니다. 따라서 더 이상 포인터 오류가 발생하지 않지만 코드 속도가 다소 저하됩니다.

typedef unsigned long ID_Number; 

// create a user and return the ID 
ID_Number create_user() { 
    ID_Number new_id = assign_unique_id(); 
    struct User * node = new User(); 
    node->_id = new_id; 
    node->_data = ... // whatever, set it up here 
    add_to_users_dict (new_id, node); 
    return new_id; 
} 

list <ID_Number> users; 

for_each (users.begin(), users.end(), process_user); 

void process_user (ID_Number i) { 
    struct User * u_ptr = lookup_user_dict (i); 
    if (u_ptr == NULL) { 
    // not found in dict 
    // somehow this guy was deleted 
    } else { 
    // we can do stuff with this guy 
    } 
} 

지금 나는 종류의 친숙한 프로그래밍의 기본 신조로 생각하지만, 독학으로 아마추어 인 내가 업계 관행과 도구에 익숙하지 않다. 기본적으로 요구되는 것은 메모리 관리에 대한 지침입니다.

1) 내가 옳고 그른 일은 무엇인가?

2) 내가 사용할 수있는 패키지 나 라이브러리가 있습니까?

3) 업계의 표준 관행은 무엇입니까?

4) 기본적으로 염소 등을 검색하기 위해 무엇을 검색해야합니까?

오늘 나는 보통 파이썬을 사용하여 나를 위해 많은 "백엔드"자료를 처리하지만 C 또는 C++이 필요하다. (나는 평범한 C 플러스 stdC++ 라이브러리를 사용하고있는 것으로 추측된다. 언어 사이의 겹침은 - 속도와 성능면에서이 특정 프로젝트에 대해 g ++ 컴파일을 잘 알고 있음을 알고 있습니다. 일부 수학 천재가 알고리즘 픽스를 제공 할 수 있다고 의심하지만 결국 별도의 질문이긴하지만 속도를 높일 수는 없습니다.

+2

'shared_ptr '을보고 시작하십시오. 내가 사용하는 거라고 –

+0

첫 번째 도구는 Valgrind의이다 : http://valgrind.org/docs/manual/QuickStart.html – Anycorn

+10

조회 RAII. 이것은 다소 미친 짓이다. 당신이 [좋은 C의 ++ 책]에서 혜택을 많이 거라고처럼 –

답변

5

내가 줄 수있는 가장 좋은 대답은 포인터를 전통적인 방식으로 사용하면 안된다는 것입니다. C++ 11은 프로그래머가 메모리 관리를 처리하는 방법을 변경했습니다.

자신보다 훨씬 지능적인 사람들이 이미 자세히 설명한 내용을 설명하기보다는 몇 가지 링크를 제공 할 것입니다. (가) 먼저 살펴 봐야

그런 다음 C++11 Style

당신이해야 새로운 C++ 11 표준을 사용 할 수 있다면, 그것은 메모리 관리를 많이하게 비얀 스트로브 스트 룹에 의해 비디오를 체크 아웃 허브 셔터의 제 Elements of Modern C++ Style 입니다 이전보다 더 깨끗합니다.

+2

그리고 C++ 11 (headhunter를 부르세요!)을 사용할 수 없다면 C++ 03에서 작동하는 수동으로 메모리를 관리하지 않는 것에 대한 많은 것들이 있습니다. –

1

1) 내가 옳고 그른 일은 무엇인가?

당신은 자원 수집을 사용하지 않는 초기화 (RAII) 관용구 또는 현대 C++ 소유권 의미입니다.

2) 내가 사용할 수있는 패키지 또는 라이브러리가 있습니까?

실제로 포인터를 전달해야하는 경우 std :: unique_ptr 및 std :: shared_ptr을 사용할 수 있습니다. 하지만 그 전에 RAII 의미를 가진 리소스 소유자로서 자신의 객체를 동작시키는 방법을 배워야합니다.

3) 무엇 업계의 표준 관행?

4) 기본적으로 염소 등을 검색하기 위해 무엇을 검색해야합니까?

RAII 내가 옳고 그른 일을하고 무엇

2

?

본질적으로 핸들을 사용하여 직접 포인터 대신 개체를 참조하는 시스템을 만들었습니다. 이는 일부 시나리오에 적합 할 수 있습니다. 운영 체제는 종종 OS가 객체를 "소유"하고 수명을 관리하지만 클라이언트가 객체를 참조 할 수있게 할 때 핸들을 사용합니다.

저에게 도움이되는 패키지 또는 라이브러리가 있습니까?

현대 C++의 표준 라이브러리에는 shared_ptr과 unique_ptr이 있습니다.이 포인터는 동적 객체의 수명을 관리하는 스마트 포인터입니다. 그들은 RAII를 사용하는 좋은 방법입니다.

무엇 업계의 표준 관행?

C++의 사실상 표준은 RAII입니다. 리소스 할당은 초기화입니다. RAII는 생성자에게 할당을 할당하고 소멸자에게 할당을 할당합니다. C++은 식별자와 실행 방법에 대한 확실한 보장을 제공하기 때문에 누출없이 객체 수명을 관리 할 수있는 완벽한 방법을 제공합니다. 스마트 포인터 shared_ptr 및 unique_ptr은 또한 객체의 소유권을 명시 적으로 지정합니다.

기본적으로 나는 찌르레기 등으로 무엇을 검색해야합니까? RAII에 대한

검색합니다.

1

첫 번째 오류는 new을 사용하는 것입니다.

동적 메모리는 거의 필요하지 않으며 "직접"필요한 것보다 희귀합니다. 가장 동적으로 할당 된 개체는 컨테이너 내에 있습니다 (예 : vector 또는 map).

당신은 무엇 클래스 불변가와 생성자를 가능하게하는 방법, 다음 (자원 획득은 초기화가) RAII의 이점을 취할 수와 C

코딩 중지 이해하면 두 번째 오류가 생성자를 사용하지 않는 것입니다
+0

래퍼를 스택에서 제거 할 때 dtor가 자동으로 호출되도록 ctor/dtor를 감싸기 시작했습니다. 그래서 RAII를 사용하면 한 인스턴스의 인스턴스를 두 개의 다른 목록에 넣을 수 있습니까? 나는 레퍼런스를 사용해야 할까? 그렇다면 어떻게 목록 A가 무언가를 반복하는 것을 막을 수 있습니까? 그것은 각각의 구조체에 "is_deleted_skip_me"부울을 추가해야하고 (주기적으로 삭제해야하는 것처럼 보입니다) 모든 단일 목록이 변경 될 때마다 목록을 계속 정리해야합니까? 편집 : 나는 많은 별도의 목록이 필요한 경우 응용 프로그램이 제대로 설계되지 않았다고 생각하기 시작합니다. – gecko

+0

@ gecko : 귀하의 제약 조건을 모르지만 많은 상호 의존 목록이 나쁘게 보입니다. 각 목록에 자체 복사본이 있도록 정보를 복사 할 수 있습니까? 그렇지 않으면, 항상'shared_ptr'을 사용할 가능성이 있지만, 길 아래의 어려움에 대한 문을 열어줍니다. –

+0

컨테이너 내부 (자체는 동일한 구조체의 다른 인스턴스 - 이름과 용량 만 다름)의 상자 (데이터 객체)이므로 컨테이너의 내용 목록이 있습니다. 상담원은 마지막 N 개의 항목을 기억합니다. 따라서 상담원이 상자를 컨테이너에 넣으면 두 항목이 같은 항목입니다. – gecko