구조체 문자열 합치기를 만들었는데 뻑나서~ 도와주세여

skylandi의 이미지

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct _Msg
{
	int iLen;
	char *pMsg;
};

bool StructCat(struct _Msg *,struct _Msg *);

int main()
{
	struct _Msg aMsg,bMsg,cMsg;
	char buf[1024];

	strcpy(buf,"abcde");
	bMsg.iLen=strlen(buf); 
	bMsg.pMsg=buf;

	memset((void *)&aMsg,0,sizeof(aMsg));

	StructCat(&aMsg,&bMsg);

	strcpy(buf,"fghij");
	cMsg.iLen=strlen(buf);
	cMsg.pMsg=buf;

	StructCat(&aMsg,&cMsg);

	aMsg.pMsg[aMsg.iLen]='\0'; 

	printf("%d %s",aMsg.iLen,aMsg.pMsg);

	free(aMsg.pMsg);
	return 0;
}

bool StructCat(struct _Msg *pStruct1,struct _Msg *pStruct2)
{
	struct _Msg Temp;

	memcpy((void *)&Temp,(const void *)pStruct1,sizeof(*pStruct1));

	pStruct1->iLen=Temp.iLen+pStruct2->iLen;
	pStruct1->pMsg=(char *)calloc(pStruct1->iLen,sizeof(char));

	if(Temp.pMsg != NULL) 
	{
		strncpy(pStruct1->pMsg,Temp.pMsg,Temp.iLen);
	}

	strncpy(pStruct1->pMsg+Temp.iLen,pStruct2->pMsg,pStruct2->iLen);

	free((void *)Temp.pMsg); //이부분이 뻑

	return 1;
}

새해 복 마니 받으시길...

더 좋은 방법이 있으시면 리플좀 달아 주세영 ^^

bw001730의 이미지

int main()
{
   char buf[1024];
  ..........
}

bool StructCat(struct _Msg *pStruct1,struct _Msg *pStruct2)
{
   struct _Msg Temp;

   memcpy((void *)&Temp,(const void *)pStruct1,sizeof(*pStruct1));
}

memcpy 하면 Temp.pMsg 가리키는 메모리는 buf 입니다.
free((void *)Temp.pMsg); //이부분이 뻑

함수안에서 buf[1024] 라고 선언하면
이 메모리는 free 할수 없습니다. 선언한 함수가 리턴한 후에 자동으로 소멸되야
되거든요. buf[1024]가 할당된 메모리는 스택영역이라고 합니다.
스택영역에는 함수안에서 선언한 변수들도 있습니다.
이모두가 함수리턴후에 사라집니다.
결국 free 하려고 하는 메모리가 buf[1024] -----> 스택
이므로 뻑나는것 같네요

buf = malloc(1024); 를 할당해서 하시면 동작은 되겠군요
malloc 하면 힙영역에 생성됩니다.
힙영역에 생성된 메모리는 free에 의해서 명시적으로소멸시켜야 합니다.

char buf[1024]; // 스택, 함수 리턴후 자동소멸
char *cp = malloc(1024); // 힙, free에 의해서 소멸

void simple()
{
        char  a[10];
        returnn ; // 이때 a가 자동 소멸e.
}
lenani의 이미지

뻑나는 원인은 auto 변수를 강제로 동적할당 해제하려고 했기 때문입니다.
예를 들면,

#include <stdlib.h>

void main() {
      int a = 3;
      free(a);   // <--- 여기서 뻑이 난다!
}

그리고 만약 C++을 사용할줄 아는걸 알고 있는데 될수 있으면 C++을 사용하면 좋은 결과를 얻을수 있습니다. 위와 같이 스트링을 사용해야 한다면 스트링 클래스를 만들어 사용하면 좋습니다.


const char * NullString = (char *) 0;
const char NullCharacter = '\0';

class String
{
private:
	char * _content;
	int _lenth;

public:
	String();
	String(const String & originalString);
	virtual ~String();

	void addString(const String & anotherString);
	void copy(const String & originalString);
	void setContent(const char * rawString);
	void empty();	
	
	const char * content() const;
	const int length() const;
};

String::String() {
	_content = NullString;
}

String::String(const String & originalString) {
	copy(originalString);
}

String::~String() {
	empty();
}

void String::addString(const String & anotherString) {
	int sufficientSize = length() + anotherString.length() - 1;	// duplication of terminating null character!
	char * temporaryCharBuff = new char [sufficentSize];

	strlcpy(temporaryCharBuff, content(), length());
	strlcat(temporaryCharBuff, anotherString.content(), anotherString.length());

	empty();
	setContent(temporaryCharBuff);	
}

void String::copy(const String & originalString) {
	setContent(originalString.content());
}

void String::allocateSpace(const int spaceLimiter) {
	empty();

	_content = new char [spaceLimiter];
	_content[0] = NullCharacter;		// For safe guarding from reading the content!
}

void String::setContent(const char * rawString) {
	int rawStringLength = strlen(rawString);

	if (length() < rawStringLength) {
		allocateSpace(rawStringLength);
	}

	strlcpy(_content, rawString, rawStringLength);
	_length = rawStringLength;	
}

void String::empty() {
	if (_content != NullString) {
		delete _content;
	}

	length = 0;
}

const char * String::content() {
	return _content;
}

const int String::length() {
	return _length;
}

여기서 방금 만들어서 버그가 있을수 있습니다. 객체지향이 만병통치약 이라고는 절대로 할수 없을 겁니다. 객체지향 프로그래밍이나 구조적 프로그래밍, 정보 공학 등등도 다 쓰임새가 있고 장단점이 있습니다.

객체 지향 프로그래밍의 장점중 하나는 바로 Abstraction 입니다. 구조적 설계를 사용하더라도 충분히 사용할수 있습니다. 구조적 프로그래밍 언어인 C에서도 사용할수 있지만 C++을 추천합니다. C++은 구조적인 면과 객체지향적 면을 동시에 지원하게 설계되어 있습니다.

만약 스트링 처리 부분만 클래스를 사용하고 나머지 부분은 보통 C언어를 쓰듯이 사용한다면 객체지향의 장점과 구조적 방식의 장점을 부분적으로 나마 동시에 이용할수 있을겁니다.

그리고 C++을 아시는 분 같은데 C++을 안쓰면 섭섭(?) 하지요... :P

죠커의 이미지

짝이 안맞는 동적할당은 위험합니다.
malloc과 free가 짝이 되어야 합니다.

malloc으로 만들었을때는 free를 꼭해주시고 그냥 선언한 변수에는 쓰지 마세요.

어떠한 경우에도 지키셔야 합니다. :-)

PS: C++ 답글을 쓰신 lenani님은 C++에 대한 애정이 지나치신것 같습니다. :-)

eungkyu의 이미지

lenani wrote:
그리고 만약 C++을 사용할줄 아는걸 알고 있는데 될수 있으면 C++을 사용하면 좋은 결과를 얻을수 있습니다. 위와 같이 스트링을 사용해야 한다면 스트링 클래스를 만들어 사용하면 좋습니다.

...

그리고 C++을 아시는 분 같은데 C++을 안쓰면 섭섭(?) 하지요... :P

C++을 아시는분이라면, std::string은 안쓰시나요? ;; 왜 꼭 만들어 쓰시려고 하는지...
C++은 좋아하시는데 표준 라이브러리는 마음에 안드시나요? :(

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.