strtok 을 통해 얻어진 토큰에 접근후 메모리 오류발생 문제

jinseo1224의 이미지

문제가 없었던 프로그램에 토큰을 이어붙인 스트링을 사용해야해서 밑의 함수를 추가 하였습니다.

세그폴트가 발생되어 밑의 코드들을 주석처리 해보니 다시금 정상작동 하더라구요..

노가다를 통해서 확인해본 결과
sprintf(psResult,"%s",psTemp);
strncpy(psResult, psTemp, strlen(psTemp));
memcpy(psResult, psTemp, strlen(psTemp));

세개중 하나의 함수로 strtok 의 결과물 psTemp 에 접근한 후에
다른함수에서 메모리 오류가 발생하네요..

printf 로 접근했을시에는 오류가 나지 않고
psResult에 "What" 이라는 임의의 값을 넣고 진행했을때도 오류가 나지 않더라구요...

이것이 당췌 무슨 이유에서인지 모르겠네요 ㅠㅠ

OS 는 HP-UX B.11.23 U ia64 2333129302 unlimited-user license 입니다.

[에러 케이스 1]
Program received signal SIGSEGV, Segmentation fault
si_code: 1 - SEGV_MAPERR - Address not mapped to object.
[Switching to thread 2 (system thread 245277)]
0x9fffffffe6ffbd70:0 in real_malloc+0x670 () from /usr/lib/hpux64/libc.so.1
(gdb) bt
#0 0x9fffffffe6ffbd70:0 in real_malloc+0x670 () from /usr/lib/hpux64/libc.so.1
#1 0x9fffffffe6ffb510:0 in _malloc+0x7d0 () from /usr/lib/hpux64/libc.so.1
#2 0x9fffffffe70066b0:0 in malloc+0x140 () from /usr/lib/hpux64/libc.so.1
#3 0x9fffffffe6fc2570:0 in calloc+0x200 () from /usr/lib/hpux64/libc.so.1
#4 0x9fffffffe77b4330:0 in 제가 만든 함수_1()

[에러 케이스 2]
Program received signal SIGSEGV, Segmentation fault
si_code: 1 - SEGV_MAPERR - Address not mapped to object.
[Switching to thread 2 (system thread 245565)]
0x9fffffffe6ffbd70:0 in real_malloc+0x670 () from /usr/lib/hpux64/libc.so.1
(gdb) bt
#0 0x9fffffffe6ffbd70:0 in real_malloc+0x670 () from /usr/lib/hpux64/libc.so.1
#1 0x9fffffffe6ffb510:0 in _malloc+0x7d0 () from /usr/lib/hpux64/libc.so.1
#2 0x9fffffffe70066b0:0 in malloc+0x140 () from /usr/lib/hpux64/libc.so.1
#3 0x400000000008f3d0:0 in 만든 함수_2()

인자값
("www.test.com", "." , 0 , 2 , str[LENGTH] ) 요롷게 들어값니다.
실행 결과는 str[LENGTH] = "www.test" 입니다.

int get_sequence_tokens(char * psTarget, char* psSeparator,int nStartPosition, int nNumTokens, char * psResult)
{
	char psStr[LENGTH];
	char * psTemp;
	int i;
 
	memset(psStr, 0x00, LENGTH);
	memset(psTempforFree, 0x00, LENGTH);
 
	strncpy (psStr, psTarget, strlen(psTarget));
 
	psTemp = strtok(psStr, psSeparator);
 
	for (i=nStartPosition ; i<nNumTokens ; i ++){
		if(i==nStartPosition){
			//printf("psTemp['%s}\n",psTemp);
			//sprintf(psResult,"'%s",psTemp);
			//strncpy(psResult, psTemp, strlen(psTemp));
                        //memcpy(psResult, psTemp, strlen(psTemp));
			//strncpy(psResult, "What",strlen("What"));
 
			continue;
		}
 
		if(NULL == (psTemp = strtok(NULL,psSeparator)))
		{
			return -1;
		}
		else{
			//strcat(psResult, psSeparator);
			//strcat(psResult, psTemp);
		}
	}
	return 0;
}
익명 사용자의 이미지

이코드가 에러가 난다는 말씀인가요??

$ cat a.c
#include <stdio.h>
#include <string.h>
 
#define LENGTH 1000
 
int get_sequence_tokens(char * psTarget, char* psSeparator,int nStartPosition, int NumTokens, char * psResult)
{
        char psStr[LENGTH];
        char * psTemp;
        int i;
 
        memset(psStr, 0x00, LENGTH);
 
        strncpy (psStr, psTarget, strlen(psTarget));
 
        psTemp = strtok(psStr, psSeparator);
 
        for (i=nStartPosition ; i<nNumTokens ; i ++){
                if(i==nStartPosition){
                        //printf("psTemp['%s}\n",psTemp);
                        sprintf(psResult,"'%s",psTemp);
                        strncpy(psResult, psTemp, strlen(psTemp));
                        //strncpy(psResult, "What",strlen("What"));
 
                        continue;
                }
 
                if(NULL == (psTemp = strtok(NULL,psSeparator)))
                {
                        return -1;
                }
                else{
                        strcat(psResult, psSeparator);
                        strcat(psResult, psTemp);
                }
        }
        return 0;
}
 
int main()
{
        char str[LENGTH];
        get_sequence_tokens( "www.test.com", "." , 0 , 2 , str ) ;
        fprintf( stderr, "str=\"%s\"\n", str );
        return 0;
}
int main()
{
    char str[LENGTH];
    get_sequence_tokens( "www.test.com", "." , 0 , 2 , str ) ;
    fprintf( stderr, "str=\"%s\"\n", str );
    return 0;
}

$ gcc a.c
$ ./a.out
str="wwww.test"
}}}
jinseo1224의 이미지

정확히는 이 코드에서 에러가 나는것은 아니구요

이 코드를 추가한후에 함수를 실행시키면

다른 곳에서 오류가 납니다.

제가 만든 함수_1번또는 함수_2번에서요.. 공통점은 gdb 결과에서 보시듯이 malloc 부분이구요...

복사관련된 함수를 주석처리하면 (sprintf 또는 strncpy 또는 memcpy)

malloc 관련 에러가 발생하지 않습니다

뭔가... 이 코드가 메모리 영역을 망가뜨리는건 아닐런지요...

cinsk의 이미지

strncpy()의 세번째 인자가 잘못된 것 같군요.

bacon의 이미지

코드만 보고 이야기 하면, 버퍼크기문제가 없다고 가정했을때

sprintf(psResult,"%s",psTemp);는 문제를 일으킬것 같지않고.

이 두가지는
strncpy(psResult, psTemp, strlen(psTemp));
memcpy(psResult, psTemp, strlen(psTemp));
문제를 일으킬거예요 psResult가 null-termination이 안되니까 strcat()이 나중에 호출되면 psResult다음의 내용에 따라 concatenation이 어떤 위치에서 시작할지 알수가 없죠. 윗분 말한게 이 내용인듯 하네요.

strncpy(psResult, psTemp, strlen(psTemp)+1);이나
memcpy(psResult, psTemp, strlen(psTemp)+1); 로 하던가

strcpy (psResult, psTemp)하면 되는데요. psTemp는 strtok()에 의해 이미 null-terminate되어 있으니까요.

댓글 달기

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