37. 가변배열 코드 (2)

P4·2023년 6월 20일
0
post-thumbnail

heap corruption (heap 손상)

  • 다른 데이터가 들어있는 heap 영역을 침범해서 데이터를 저장하거나?, 사용되지 않는 메모리 영역을 참조하면 일어남

  • 그 침범당한 부분에 저장된 변수를 가져오는 코드에 문제가 생김, 다른 사람 코드에서 문제를 일으킬 수도 있음

이걸 해결하려면?

  • 2칸이 꽉 차면 저장공간을 2칸 늘리는게 아니라?

  • 2 + 2 = 4 --> 즉 4개의 데이터를 넣을 메모리공간을 아예 처음부터 새로 받아야함



코드

Arr.h

#pragma once

typedef struct _tagArr
{
	int* pInt;
	int iCount;
	int iMaxCount;

}tArr;

// 배열 초기화 함수
void InitArr(tArr* _pArr);

// 데이터 추가 함수
void PushBack(tArr* _pArr, int _iData);

// 공간 추가 확장
// void Reallocate(tArr* _pArr);
// 이걸 헤더파일에서 주석처리한 이유는?
// main 함수에서 만약에 이걸 호출하면 배열이 가득차지도 않았는데 뜬금없이 크기가 2배 증가함
// 그래서 main 함수에서 사용되지 못하게 하려고 주석처리 해준거임
// 어차피 cpp 파일에서는 이 함수가 구현되어 있으므로 아무 문제 없음, main 함수에서 사용되지 않는 함수는 이렇게 막아줄 수도 있음

// 배열 메모리 해제 함수
void ReleaseArr(tArr* _pArr);


Arr.cpp

#include "Arr.h"
#include <iostream>

void InitArr(tArr* _pArr)
{
	_pArr->pInt = (int*)malloc(sizeof(int) * 2);
	_pArr->iCount = 0;
	_pArr->iMaxCount = 2;

}

void Reallocate(tArr* _pArr)
{
	// 1. 2배 더 큰 공간을 할당한다.
	int* pNew = (int*)malloc(_pArr->iMaxCount * 2 * sizeof(int));
	// pInt에 바로 넣어버리면 기존의 주소는 아무도 가리키지 않음
	// 데이터가 날라감

	// 2. 기존 공간에 있던 데이터들을 새로 할당한 공간으로 복사시킨다.
	for (int i = 0; i < _pArr->iCount; ++i)
	{
		pNew[i] = _pArr->pInt[i];
	}

	// 3. 기존 공간은 메모리 해제
	free(_pArr->pInt);

	// 4. 배열에 새로 할당된 공간을 가리키게 한다.
	_pArr->pInt = pNew;

	// 5. iMaxCount 변경점 적용
	_pArr->iMaxCount *= 2;
	// 호출될때마다 영역크기를 얼마나 늘릴지는 만든 사람이 정하는 것
	// 여기서는 2배씩 늘리기로 함
}

void PushBack(tArr* _pArr, int _iData)
{
	// 힙 영역에 할당한 공간이 다 참
	if (_pArr->iMaxCount <= _pArr->iCount)
	{
		// 재할당
		Reallocate(_pArr);
	}

	// 데이터 추가
	_pArr->pInt[_pArr->iCount++] = _iData;

	/* 현재 인덱스에 데이터를 추가, 데이터를 추가한 뒤 후위 연산자로 인해
	문장이 끝날때 iCount가 1증가 */
}

void ReleaseArr(tArr* _pArr)
{
	free(_pArr->pInt);
	_pArr->iCount = 0;
	_pArr->iMaxCount = 0;
}
  • iMaxCount가 호출마다 2배씩 증가하는건 사용자 재량으로 정한 크기 증가량임


main.cpp

#include <stdio.h>
#include <iostream>

#include "Arr.h"

int main(void)
{
	tArr arr = {};
	
	InitArr(&arr); // 초기값 설정

	for (int i = 0; i < 10; ++i) // 가변배열에 데이터 10개 넣기, (0 ~ 9)
	{
		PushBack(&arr, i); // 데이터 넣기 함수
	}

    for (int n = 0; n < 10; ++n)
	{
		printf("%d", arr.pInt[n]);
	} // 데이터가 잘 들어갔음을 확인가능

	ReleaseArr(&arr); // 메모리 해제, count, maxcount 초기화

	return 0;
}
  • 만약 main 함수에서 호출되지 못하게 만들고 싶은 함수가 있다면 그걸 헤더파일에서 빼고 (주석처리) cpp 파일 내에서만 자체적으로 사용되게 만들면 됨
profile
지식을 담습니다.

0개의 댓글