[완료] Segmentation Fault 가 발생했습니다.

hyper9의 이미지

문제가 발생한 곳은요 ~
아래와 같습니다. printf()을 실행할 때 바로 segmentation fault가 생깁니다.

.
.
SSL_CTX *ssl_ctx;
.
.
.
ssl_ctx = get_ssl_ctx();
printf("ssl_ctx->method = %x \n", ssl_ctx->method);
.
.

위의 code중에서 get_ssl_ctx() function의 내부에서 SSL_CTX 구조체를 초기화 합니다.
get_ssl_ctx() function은 대략 아래와 같은 모양입니다.

SSL_CTX *get_ssl_ctx()
{
SSL_CTX *ssl_ctx;
.
.
  printf("ssl_ctx->method = %x \n", ssl_ctx->method);
  return ssl_ctx;
}

위와 같이 get_ssl_ctx()안에서 ssl_ctx->method를 print하면 제대로
보이지만, get_ssl_ctx()에서 return된 이후에 print를 하면
segmentation fault가 나는 이유가 뭘까요?

조언을 부탁드립니다.
어떻게 debugging을 시작해 보는 것이 좋을지 알려주시는 것도 역시 감사드립니다. ^^

chadr의 이미지

올려주신 소스의

.
.

이 부분이 가장 의심이 가는군요..
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

hyper9의 이미지


제 설명이 부족했는지 몰라도 일단은 get_ssl_ctx() function은 SSL_CTX 구조체를 return하고 있고요
그 구조체를 return하는 "return ssl_ctx" 바로 직전에 ssl_ctx->method를 print했을 때, 제대로
초기화 된 값을 볼 수 있었고요.

그리고 get_ssl_ctx()에서 return된 값을 바로 get_ssl_ctx() function을 호출한 function에서
print했을 때, ssl_ctx->method를 print하면 segmentation fault가 발생했던 것인데요.

제 생각에는
.
.
부분은 그렇게 중요하다고 생각이 들지 않았거든요.
일단은 segmentation fault가 발생하는 바로 근처만을 올린 것이고,,
사실 .... 부분은 SSL_CTX를 초기화하는 부분입니다.

제 생각이 뭔가 틀린건지도 모르겠네요.
조언 부탁드립니다.

bootmeta의 이미지

즉 function 내부에서 ssl_ctx pointer가 가르키고 있는 부분이 stack(local variable)인지, heap memory alloc 영역인지, 아니면 기타이유인지 기존 code만 가지고 판단하기가 애매하다는 뜻이겠죠.

만일 ssl context 구조체(?)가 local 변수라면, get_ssl_ctx() return후 ssl_ctx pointer는 invalid하겠죠.

hyper9의 이미지

다시 확인해서 update하겠습니당. ~ ^^

hyper9의 이미지

위에 올렸던 내용 중에 잘못된 것이 있어서, 아래와 같이 수정했습니다.

.
.
SSL_CTX *ssl_ctx;
.
.
.
ssl_ctx = get_ssl_ctx();
printf("ssl_ctx->method = %x \n", ssl_ctx->method);
.
.

아래에서 보시는 바와 같이 ssl_ctx2는 get_ssl_ctx() 바깥쪽에 static으로
선언되어 있었습니다.

static SSL_CTX *ssl_ctx2;
.
.
.
.
SSL_CTX *get_ssl_ctx()
{
 
.
.
  // SSL_CTX is initialized here.
.
.
  printf("ssl_ctx2->method = %x \n", ssl_ctx2->method);
  return ssl_ctx2;
}

생략된 부분은 주로 SSL_CTX에 내용을 채워넣은 초기화 과정입니다.
이걸 보면 위에서 조언을 주신 것처럼 일단 ssl_ctx2가 local은 아닌 것 같습니다.

조언 부탁 드립니다. 감사합니다. ~

bootmeta의 이미지

예를 들어
실행 platform과 버전
사용 compiler와 버전
관련 라이브러리와 버전

최대한 관련 정보를 제공할 수록 답변이 붙을 확률이 높아집니다.
딱히 문제가 되지 않는다면 생략된 code까지 올려주시거나, 같은 error가 발생하는 test code를 올려주시면 더 높아지겠죠.

ps)
google 검색을 해보니 OPEN SSL 라이브러리 관련 문제같군요.
google "SSL_CTX seg fault"로 올라온 답변들을 참조해보면
1) SSL_library_init();를 빼먹었는지 확인
2) SSL_CTX를 비롯해 여러 context가 적절히 설정되었는지 return code등으로 확인할 것
3) 일단 최적화 option을 off하고 debug mode에서 test

http://www.mail-archive.com/openssl-users@openssl.org/msg59073.html

hyper9의 이미지

지금 이 code가 32bit machine에서 compile하고 실행했을 때는
문제가 없었는데,
64bit machine에서 문제가 생긴 상태입니다.

그리고 또 다른점은 ,,32bit machine은 Fedora 7이었고,
지금 64bit machine은 Fedora11 입니다.

따라서 SSL library와 gcc compiler도
32bit에서는 Fedora7에 있는 것으로
64bit에서는 Fedora11에 있는 것으로 사용했습니다.

다른 내용도 확인해서 update하겠습니다.

hyper9의 이미지

일단 get_ssl_ctx()함수가 return되기 직전에 ssl_ctx2의 값을 print해보면,,
0xfffffffff0002750 이라고 보입니다. (물론 이 address는 시도할 때마다 바뀌네요)

하지만 get_ssl_ctx()에서 return되고 난 후에 print해보면,
0xfffffffff0002750: Cannot access memory at address 0xfffffffff0002750이라고
나오네요..

아직 이유는 모르겠습니다.

klara의 이미지

저역시
.
.
부분이 중요하다고 추측됩니다..특히 '초기화'라고 하신부분이요.
예를 들면, 그럴린 없다고 생각하지만, get_ssl_ctx안에서

SSL_CTX ctx;
ssl_ctx = &ctx;

같은 엉터리 코드일지 아닐지 어찌 알겠습니까...

mac040의 이미지

저도 스택 값의 주소를 포인터에 저장하여 리턴 했다에 한표겁니다.

정 애매모호하시면 valgrind를 돌려보시면 명확해질 듯 합니다.

hyper9의 이미지

return하고 있는 것은 ssl_ctx2인데요..

설사 말씀하신 엉터리 코드가 있어도,
return하고 있는 것이 ssl_ctx2이기 때문에 결과와는 아무 상관없다는
생각이 드는데요,,

제가 잘못생각하는 걸까요?

dorado2의 이미지

ssl_ctx2가 local이 아니더라도 어디를 pointing하고 있느냐에 따라 충분히 문제가 생길 수 있습니다.

hyper9의 이미지

이 문제를 똑같이 재현하는 sample code를 올리는 게 좋겠네요 ^^
다들 생각하시는 방향이 다를 수 있으니까요..

아마 하루 이틀내로 준비할 수 있을 것 같습니다.
갑자기 많이 바빠져서 ㅜㅜ

아뭏든 감사드립니다 ~

klara의 이미지

정말 제가 적은 코드에서 무엇이 문제인지 모르시겠다면 변수의 범위에 대해 공부해보시는게 좋을것 같습니다-_-;;

hyper9의 이미지

get_ssl_ctx()에서 사용되는 변수도 아니고,
물론 생략된 부분에 있을 거라고 추측을 하셨겠지만,
local에서 사용되다가 어떻게 되었더라도..

결국은 ssl_ctx2라는 변수가 return되는 것이라서
그렇게 생각했는데요..

뭔가 변수의 범위에 관해서 잘못알고 있는 걸까요?

junkl의 이미지

int * global_int;
 
int *
sub_func(void)
{
   int local_number;
   int * local_int = &local_number;
 
   global_int = local_int;
   return local_int;
}
 
void
main_func()
{
    int * local_int;
    local_int = sub_func();
}

위와 같은 경우 주소는 글로벌에 저장되어 있지만.. 실제 내용은 로컬이죠

hyper9의 이미지

제가 다시 한번 확인후에 다시 글을 올리겠습니다.
정말 그 이유라면 시원할 것 같습니다. ^^

다시 감사드립니다 ~

chriskr7의 이미지

pointer에 malloc으로 heap메모리를 할당하고
초기화 하고 리턴하는지 확인이 필요할 것 같습니다.

hyper9의 이미지

갑자기 바쁜일이 생겨서 늦어졌습니다.
일단 전체 source를 아래와 같이 올립니다.
file은 3개입니다.

첫번째 file인 main.c 입니다.

extern void *ssl_thread(void);
 
int main(void)
{
   int         err = 0;     
   pthread_t   tid;     
   SSL_library_init();
 
   err = pthread_create(&tid, NULL, &ssl_thread, NULL);
   while(1)
   {    
 
   }    
}

두 번째 file은 aaa.c 입니다.

void *ssl_thread(void)
{
   SSL_CTX         *ssl_ctx;
 
   while(1)
   {
       printf("ssl_thread #1 \n");
       ssl_ctx = get_ssl_ctx();
       printf("ssl_thread #2 [%x] \n", ssl_ctx->method);
   }
}

세 번째 file은 aaa.c 입니다.

static SSL_CTX *aaa_ctx;
 
SSL_CTX *get_ssl_ctx()
{
   if ((aaa_ctx = SSL_CTX_new(SSLv23_method())) == NULL)
   {
      return NULL;
   }
 
   printf("get_ssl_ctx [%x] \n", aaa_ctx->method);
 
   return aaa_ctx;
}

실행 결과는 예상하시겠지만,,,aaa.c의 두번째 print문에서 Segmentation Fault가 납니다.
실행환경은 Fedora 11 / 64bit 입니다.

하지만, 이 program들을 동일한 방법으로 Fedora 7/32bit에서 compile한 후 실행하면
Segmentation Fault없이 aaa.c의 두번째 print문이 성공적으로 잘 보입니다.

source 올리는게 늦어져서 죄송하고요,,조언 주시면 감사하겠습니다. ^^

hyper9의 이미지

aaa.c의 두번째 print문은
printf("ssl_thread #2 [%x] \n", ssl_ctx->method); 입니다.

bbb.c의 print문은
printf("get_ssl_ctx [%x] \n", aaa_ctx->method); 입니다.

bushi의 이미지

[bushi@rose tmp]$ ls -l
합계 24
-rw-rw-r-- 1 bushi bushi 236 2010-02-26 05:25 aaa.c
-rw-rw-r-- 1 bushi bushi 225 2010-02-26 05:06 bbb.c
-rw-rw-r-- 1 bushi bushi 230 2010-02-26 05:24 main.c
[bushi@rose tmp]$ 
[bushi@rose tmp]$ cat -n main.c
     1	extern void *ssl_thread(void *);
     2	
     3	int main(void)
     4	{
     5	   int         err = 0;     
     6	   pthread_t   tid;     
     7	   SSL_library_init();
     8	
     9	   err = pthread_create(&tid, NULL, ssl_thread, NULL);
    10	   while(1)
    11	   {    
    12		sleep(1000);
    13	   }    
    14	}
[bushi@rose tmp]$ 
[bushi@rose tmp]$ cat -n aaa.c
     1	extern SSL_CTX *get_ssl_ctx(void);
     2	
     3	void *ssl_thread(void *unused)
     4	{
     5	   SSL_CTX         *ssl_ctx;
     6	
     7	   while(1)
     8	   {
     9	       printf("ssl_thread #1 \n");
    10	       ssl_ctx = get_ssl_ctx();
    11	       printf("ssl_thread #2 %p\n", ssl_ctx);
    12	   }
    13	}
[bushi@rose tmp]$ 
[bushi@rose tmp]$ cat -n bbb.c
     1	static SSL_CTX *aaa_ctx;
     2	
     3	SSL_CTX *get_ssl_ctx()
     4	{
     5	   if ((aaa_ctx = SSL_CTX_new(SSLv23_method())) == NULL)
     6	   {
     7	      printf("null\n"); 
     8	      return NULL;
     9	   }
    10	
    11	   printf("get_ssl_ctx %p\n", aaa_ctx);
    12	
    13	   return aaa_ctx;
    14	}
[bushi@rose tmp]$ 
[bushi@rose tmp]$ 
[bushi@rose tmp]$ gcc -Wall -o test *.c -include /usr/include/openssl/ssl.h -include /usr/include/stdio.h -include /usr/include/pthread.h -include /usr/include/unistd.h `pkg-config --cflags --libs openssl`
[bushi@rose tmp]$ 
[bushi@rose tmp]$ ./test

OTL

hyper9의 이미지

감사합니다..이젠 잘 됩니다...

bushi의 이미지

뭣 때문에 seg.fault가 발생했는지 아셨습니까 ?

전,
ssl_ctx = get_ssl_ctx();
에서 행해진 묵시적인 형변환때문이라 생각하지만,
워낙 단촐한 코드를 올리셔서 확신을 할 수 없었습니다.
컴파일러가 분명히 경고를 했을텐데 그걸 무시하셨을리가 없으니까요.

뭐가 문제였었던겁니까 ?

OTL

hyper9의 이미지

제 원래의 code에 없었는데, compiler가 경고를 하는 것 같지 않던데요.

올려주신 code를 보면서 비교해보고 get_ssl_ctx()의 extern declaration을 추가하고
난 후에 segmentation fault가 발생하지 않습니다.

그런데,,이게 Fedora 7에서는 문제없던 code였는데,
Fedora 11에서 문제가 생겼었고요.

더군다나 예전에 Fedora 7에서 문제가 없었기때문에 declaration을 제대로 살펴보지 않았던
것도 사실입니다.

선언이 되어 있지 않았을 경우에 Compiler의 행동이 Fedora 7에서와 Fedora 11에서의
경우가 다른 것 같다고 이해를 해버렸는데,,,
너무 쉽게 넘어가고 있는 것인지도 모르겠습니다.

bushi의 이미지

코더가 가르쳐주지 않는다면, 컴파일러는
int get_ssl_ctx();
로 가정하고 컴파일합니다.
컴파일러가 가정한 이 코드는 sizeof(int)==sizeof(void*)인 모든 플랫폼에서 아무런 문제 없습니다.
64bit 에선 다릅니다.

http://kldp.org/node/103442#comment-478641 에 다른 분의 경험담이 있습니다.

OTL

sangwoo의 이미지

-Wall 옵션을 넣어도 경고가 안나오나요? 기억이 잘... 나중에 실험해보고 다시 글 올릴께요~
----
Let's shut up and code.

----
Let's shut up and code.

hyper9의 이미지

그건 좋은 정보이네요.
감사합니다. ^^

댓글 달기

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