2012-03-22 3 views
0

배열이 꽉 찼을 때 문자열 배열에 문자열을 저장하는 C++ 프로그램을 작성했습니다. 아래 코드를 사용하여 더 많은 항목을위한 공간을 만들기 위해 배열의 크기를 조정합니다. 하지만 때때로 (항상은 아니지만) "delete [] temp;"에서 충돌합니다. 라인과 나는 왜 그것을 어떻게 고칠 지 모른다. 도와주세요.C++ delete [] crashes

나는 많은 것을 수색했지만 어느 곳에서도 대답을 찾을 수 없었다. 내가 그것을 디버그 할 때 "잘못된 포인터"라고 말하지만, 데이터를 저장하기 전에 어떻게 잘못 될 수 있습니까? 그리고 아직 해제하지 않았습니까?

if(item_cnt >= (arr_size - 1)) 
{ 
    int oldsize = arr_size; 
    string * temp; 
    arr_size *= 2; 
    temp = arr; 
    arr = new string [arr_size]; 
    memcpy(arr, temp, oldsize * sizeof(temp)); 
    delete[] temp; 
} 
+2

스타일의 몇 가지 점 : 당신은'memcpy'가 아니라'std :: copy'를 사용해야합니다. 그리고 수동 메모리 관리 ('new','delete' 등)를해서는 안되며 컨테이너 클래스를 사용하여 자동으로 처리해야합니다. –

+3

'memcpy (arr, temp, oldsize * sizeof (temp));'- sizeof (* temp)가 아니겠습니까? (예, 물론, memcpy는 처음부터 잘못되었습니다.) –

+2

이것은 나쁜 것입니다 ... 문자열에 memcpy를 사용하지 마십시오. 'string myString (toBeCopied);'을 사용하십시오 : http://anaturb.net/C/string_exapm.htm –

답변

0

배열이 동적 크기의 배열을 구현하는 방법을 사용하는 것이 좋습니다 정말

vector<string> 

해야한다 :

이 내 코드입니다. 벡터를 사용하면 수동으로 물건을 재 할당/복사 할 필요가 없으며 사용자가 가지고있는 것과 같은 문제를 피할 수 있습니다.

+1

왜? 설명이 도움이 될 것입니다. –

-1

구식 스타일과 새로운 스타일의 메모리 작업을 혼합하는 것은 항상 나쁜 생각입니다 ... 여기서 memcpynew/delete을 사용합니다. ... delete[]는 배열의 각 요소에 대한 dtor을 호출 알고 있어야

편집 : 의 ctor -> dtor

HTH

마리오

+0

예, 죄송합니다. 너는 물론 맞았다! –

5

당신이 절대적으로 고수해야하지 않는 한 당신의 현재 접근 방식, 나는 당신의 문자열을 잡아 벡터를 사용하는 것이 좋습니다. 그것은 당신을위한 모든 기억을 관리 할 것입니다.

#include <vector> 
#include <string> 
int main() 
{ 
    std::vector<std::string> arrayOfStrings; 

    arrayOfStrings.push_back("Hello World!"); // To Add Items 
    string value = arrayOfString.at(<some index>); // To Retrieve an Item you can also use the [] operator instead of the at method 

    return 0; 
} 
+0

참고 : 어떤 이유로 배열을 가리켜 야하는 경우에도 벡터를 사용하고 포인터가 필요한 곳에서'& arrayOfStrings [0]'을 전달할 수 있습니다. – cHao

+0

사실 내 숙제입니다 (예, 부정 행위라고 불릴 수도 있지만, 제가 설명한 행동의 이유를 찾을 수 없었습니다). 그리고 여기에서 벡터를 사용할 수 없습니다. 어쨌든 팁 주셔서 감사합니다. – Dalibor

1

memcpy이 문제의 루트에 :

다음은 예입니다. 모든 사람들이 "사용하지 마십시오"라고 말했지만 왜 그것이 결국 나쁜 생각인지를 설명하게하겠습니다.

먼저 C++ 문자열은 무엇이며 어떻게 그 마법을 수행합니까? 이것은 기본적으로 가변 길이의 문자 배열이며 각 문자열 객체 내에 해당 문자를 보유하기 위해 할당 된 메모리를 가리키는 포인터를 보유함으로써이 위업을 달성합니다. 문자열이 커지거나 줄어들면 해당 메모리가 다시 할당됩니다. 문자열 을 올바르게 복사하십시오.은 내용을 '깊은 사본'으로 만드는 작업입니다.

지금, 당신의 코드 :

arr = new string [arr_size]; 

이것은 빈 문자열 객체의 배열을 만듭니다. 내부 포인터는 비어 있기 때문에 일반적으로 null입니다.

memcpy(arr, temp, oldsize * sizeof(temp)); 

나쁜 일이 발생합니다. 이것은 실제로 원래 문자열의 복사본을 만드는 것이 아니라 내부 표현을 덮어 쓰는 것입니다. 따라서 이전 문자열과 새 문자열은 모두 동일한 문자 데이터를 가리 킵니다.

delete[] temp; 

우리는 Thew 보낸 된 문자열을 삭제할 수 있지만이 또한 사용 된 문자의 메모리를 해제 : 이제 정말 나사 일까지로,이 발생합니다.따라서이 문자열의 새로운 '사본'은 실제로 해제 된 메모리를 가리 킵니다. 우리는 이제 자동차 충돌이 일어나기를 기다리고 있습니다. 문자 데이터는 어떤 것에 대해서도 재사용 될 수 있습니다. 그리고 문자열을 다시 시도하고 삭제할 때, 운영체제는 당신이 가지고 있지 않은 메모리를 제거하려고 시도하고 있음을 알게 될 것입니다 할당되었습니다.