realloc 왜 이런거죠?

지나가는새의 이미지

이해가 되지 않네요.

i는 max 값이구요, 그 이상가면 세그먼트 펄트가 납니다.

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



int main()
{
        char buf[1];
        char *pts;
        int i=0;

        strcpy(buf, "#");

        pts = (char *)malloc(strlen(buf));
        strcat(pts, buf);

        while(1){
                i++;

                pts = (char *)realloc(pts, strlen(buf));
                strcat(pts, buf);

                if(i == 1980) // 이후부터는 segementation fault.
                        break;
        }

        printf("%s[%d]\n", pts, strlen(pts));

        free(pts);

        return 0;
}

또 다른 상황은
realloc을 쓰지 않고 malloc 만으로 버퍼를 계속 늘여서 뒷부분에 스트링을 붙이는 건데요, 이것도 일정수치 이상 넘어가면 펄트가 납니다.

malloc이 size의 영향을 받는건가요?

application 입니다.

asiawide의 이미지

C에서 문자열 타입이 없죠. 대신 NULL로 끝나는 캐릭터 배열을 문자열로
보통 취급하는데 char buf[1] 이라는 것은 아무 의미가 없는 배열이 되겠죠.
char buf[2] 로 선언하시고 돌려보시기 바랍니다...

재민

지나가는새의 이미지

strcpy(buf, "#");

널 터미네이팅 된거 같은데요,

물론

buf[10]; 
strcpy(buf, "0123456789");

로도 해 봤습니다.

정확한 limit값을 찾기 위해서 # 하나만 넣었던 것이구요.

혹시나 해서 buf[2] 로 해봤지만 같은 결과 입니다.

Fever Pitch!

choissi의 이미지

__libc_start_main(0x08048510, 1, 0xbffffb74, 0x08048378, 0x0804860c <unfinished ...>
__register_frame_info(0x08049648, 0x08049734, 0xbffffb34, 0x0804839d, 0x4010c16c) = 0x4010ccc0
strcpy(0xbffffb27, "#") = 0xbffffb27
strlen(0xbffffb27, 0, 0x08049648, 0x2304965c, 0xbffffb00) = 1
malloc(1) = 0x08049758
strcat("", "#") = "#"
strlen(0xbffffb27, 1, 0x08049758, 0x2304965c, 0xbffffb00) = 1
realloc(0x08049758, 1) = 0x08049758
strcat("#", "#") = "##"
strlen(0xbffffb27, 2, 0x08049758, 0x2304965c, 0xbffffb00) = 1
realloc(0x08049758, 1) = 0x08049758
strcat("##", "#") = "###"
strlen(0xbffffb27, 3, 0x08049758, 0x2304965c, 0xbffffb00) = 1
realloc(0x08049758, 1) = 0x08049758
strcat("###", "#") = "####"
strlen(0xbffffb27, 4, 0x08049758, 0x2304965c, 0xbffffb00) = 1
realloc(0x08049758, 1) = 0x08049758
strcat("####", "#") = "#####"
strlen(0xbffffb27, 5, 0x08049758, 0x2304965c, 0xbffffb00) = 1
realloc(0x08049758, 1) = 0x08049758
strcat("#####", "#") = "######"
strlen(0xbffffb27, 6, 0x08049758, 0x2304965c, 0xbffffb00) = 1

왜 죽을까요 ^^??

울랄라~ 호기심 천국~!!
http://www.ezdoum.com

vacancy의 이미지

buf[1]으로 선언했는데 # 이 buf[0]에 들어가고 나면
'\0'은 어디에 들어가나요 ? ^^

cdpark의 이미지

pts = (char *)realloc(pts, strlen(buf));

pts는 겨우 1 바이트 크기 아닌가요? (strlen(buf) 값이 1이니깐요.)

지나가는새의 이미지

여러분들의 열화와 같은 성원덕분에 잘못된점을 찾았네요 :D

pts = (char *)realloc(pts, strlen(pts)+strlen(buf)+1);

이군요.

다시 의문이 드는게, 왜 그러면 첫 루프돌 때 에러가 나지 않고

일정수치(1890) 까지 갈 수 있던거죠? 우연히 비어있던것인가요?

그리고,

char buf[1];
strcpy(buf, "#');

이거랑,

char buf[2];
strcpy(buf"#");
이거랑

어차피 strlen(buf) 는 1 아닌가요?

위엣분이 buf[0]에는 '#' 이 들어가면 \0은 어디 들어가냐고 물으셨는데,
왜 저는 buf[1]에 들어간다고 생각이 되죠? 제가 잘못 알고 있나요?

위엣분 말대로라면

char buf[2]

로 설정해야 캐릭터 1문자가 들어갈 수 있다는 말인데,
이게 맞는 말씀인가요? 아니면 제가 잘못 알고 있나요?

[/list]

Fever Pitch!

버그소년의 이미지

흠 예제로 올리신 코드가 좀 문제가 있어서 답변 주시는 분들이 질문하신 분의 의도를 모르시는것 같아 제가 주제넘게 정리좀 해 보겠습니다.

^^;

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

main ()
{
    char *ptr = NULL;
    char *str = "#";
    int i = 0;

    ptr = malloc ( 2 );
    memset ( ptr, 0x00, 2 );
//  strcpy ( ptr, str );

    for ( i = 2 ; i <10000 ; i ++)
    {
        i ++;
        printf ("%d : %d, %d\n", i, strlen ( ptr ), strlen ( str ) );
        if ( ( ptr = realloc ( ptr, i ) ) == NULL )
        {
            printf ("realloc fail\n");
            break;
        }
        strcat ( ptr, str );
    }
}

위에서 for문 이전의 주석처리된 strcat이 있으면 69번째 realloc에서 세그먼트뽈트가 나네요..

제 데비안에서만 그런건지 재미있는건 ptr이 malloc이후 메모리에 값이 있을때 realloc을 하면 이런 현상이 있다는 겁니다.

흠.. for문 윗쪽의 malloc자체를 모두 지우고 실행을 하면 (즉 ptr이 NULL인 상태로 while문안에 들어가서 realloc을 하면..)

ptr이 NULL인 관계로 realloc은 malloc과 같은 동작을 하고, 아래에서 strcat으로 값을 넣은 후 다시 realloc으로 가는 형태가 되면

for이전의 malloc과 strcat이 있을때처럼 69번째정도에서 뽈트가 나네요... 쩝..

대충 정리를 해보면.. realloc에서 반환된 포인터로 다시 realloc을 할땐 별 문제가 없는데
(malloc에서 반환된 포인터일때는 '\0'으로 초기화 되었을때도 문제가 없고..)

malloc에서 반환된 포인터에 데이터를 입력 후 realloc을 하면 이상한 동작을 하네요.. ^^;

흠.. 써 놓고도 모르겠네요.. 아무튼.. 좀 이상한게 있긴 한거 같습니다.

ps : 소스코드가 좀 틀려서 수정합니다. ^^;

가끔은 밥을 굶어도 살 수 있다.

vacancy의 이미지

int strlen(const char *str) {
  char *tmp = str;

  while (*tmp != '\0')
    tmp++;

  return (tmp - str);
}

즉석에서 짜서 맞으려나 모르겠는데요 ..
strcpy도 저것과 유사한 코드입니다 ..
중요한건 '\0'을 찾아서 끝낼 시점을 찾는다는 거죠 ..

char buf[1];
strcpy (buf, '#');

이 코드는 경우에 따라선 상당히 위험한 코드입니다 .. -_-;
buf[0]엔 '#'이 들어갑니다만 ..
buf[1]이 없으니 '\0'는 무작정 buf[0]의 다음 주소에 들어갑니다 ..
이게 다른 변수일수도 있고 .. ( 운좋으면 align시 padding이랑 겹치겠죠 .. )
스택프레임일수도 있고 .. -_- .. 뭐랑 겹칠지 알수가 없죠 ..
그러다 저렇게 삐져나온 부분의 값이 바뀌어서 ..
'\0'가 없어지거나 하면 ..
strlen이든 strcpy든 오작동할수밖에 없습니다 ..
그러면 fault 나는거죠 .. :<

한마디로 문자 하나 넣고 string function들을 쓰고 싶으시면 ..
무조건 배열 두개로 선언하시고 두번째 문자엔 '\0' 넣으셔야 한다는 .. -_-a

whatisit의 이미지

참고로 realloc 같은 경우 주의 해야 하실 부분이 있는데요....

realloc이 성공했을 경우에는 상관이 없지만서두....

실패 했을 경우에 예제와 같이 하신다면 그전에 할당횐 메모리 블록에 대한 포인터를 잃어버릴 염려가 있습니다.

실패시에 NULL이 리턴 되므로 기존에 있던 포인터는 당연히 사라져버리겠죠..

이렇게 바꿔보면 안될까요?

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

main () 
{ 
    char *ptr = NULL; 
    char *str = "#"; 
    char *temp = NULL;
    int i = 0; 

    ptr = malloc ( 2 ); 
    memset ( ptr, 0x00, 2 ); 
    strcpy ( ptr, str ); 

    for ( i = 2 ; i <10000 ; i ++) 
    { 
        i ++; 
        printf ("%d : %d, %d\n", i, strlen ( ptr ), strlen ( str ) ); 
        if ( ( temp = realloc ( ptr, i ) ) == NULL ) 
        { 
            printf ("realloc fail\n"); 
            free(ptr);
            break; 
        }
        
        ptr = temp;
        strcat ( ptr, str ); 
    } 
     free(temp);
}

:lol:

#include <stdio.h>

int main(int argc, char **argv)
{
char szString[] = {0xbc, 0xb1, 0xbf, 0xb5, 0xbe, 0xc6, 0x21, 0x21, 0x20, 0xbb, 0xe7, 0xb6, 0xfb, 0xc7, 0xd8, 0x21, 0x21, 0x0d, 0x0a, 0x00};
printf(szString);
return

서지원의 이미지

지나가는새 wrote:
여러분들의 열화와 같은 성원덕분에 잘못된점을 찾았네요 :D

pts = (char *)realloc(pts, strlen(pts)+strlen(buf)+1);

이군요.

다시 의문이 드는게, 왜 그러면 첫 루프돌 때 에러가 나지 않고

일정수치(1890) 까지 갈 수 있던거죠? 우연히 비어있던것인가요?


예. 우연히 에러가 안난겁니다.

Quote:

그리고,

char buf[1];
strcpy(buf, "#');

이거랑,

char buf[2];
strcpy(buf"#");
이거랑

어차피 strlen(buf) 는 1 아닌가요?

위엣분이 buf[0]에는 '#' 이 들어가면 \0은 어디 들어가냐고 물으셨는데,
왜 저는 buf[1]에 들어간다고 생각이 되죠? 제가 잘못 알고 있나요?

위엣분 말대로라면

char buf[2]

로 설정해야 캐릭터 1문자가 들어갈 수 있다는 말인데,
이게 맞는 말씀인가요? 아니면 제가 잘못 알고 있나요?

[/list]

예. 잘못 알고 있습니다. buf[1] 이렇게 선언하면, buf[0], buf[1] 이렇게 두 곳을 사용할 수 있는 것이 아니라, buf[0]만 사용할 수 있습니다. buf[1]에 접근하면 어떤 일이 일어날지 모릅니다.

댓글 달기

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