'working diary'에 해당되는 글 47건

  1. 2015.12.14 #20151214-02 :: C++ :: gcc에서 runtime crash의 stacktrace를 보려면?
  2. 2015.12.14 #20151214-01 :: C++ :: "libc++abi.dylib: Pure virtual function called!"
  3. 2015.12.01 #20151201-02 :: C++ :: mongoose web server에서 mg_enable_multithreading 사용
  4. 2015.12.01 #20151201-01 :: C++ :: build cppcsp2-2.0.6 on Mac OS X
  5. 2015.01.27 #20150127-01 :: eclipse :: GC overhead limit exceeded
  6. 2015.01.26 #20150126-01 :: eclipse :: eclipse를 ubuntu launcher에 등록하기
  7. 2015.01.19 #20150119-03 :: go :: go를 이용한 TCP/IP Echo Server Example
  8. 2015.01.19 #20150119-02 :: go :: vim에서 go language 사용하기
  9. 2015.01.19 #20150119-01 :: go :: 우분투에서 go language 설치하기
  10. 2015.01.16 #20150116-03 :: ubuntu :: Android Studio 런처에 고정하기

#20151214-02 :: C++ :: gcc에서 runtime crash의 stacktrace를 보려면?

아래 링크를 참고합니다.


http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes

#20151214-01 :: C++ :: "libc++abi.dylib: Pure virtual function called!"

gtest로 모듈을 작성하던 중 "libc++abi.dylib: Pure virtual function called!"라는 런타임 에러를 만났다.

콜스택 추척도 안되고 난감했었는데, 구글링을 해보니 생성자와 소멸자에서는 순수 가상함수가 호출되면 안된다고 한다.


코드의 생성자와 소멸자들을 확인해 보니

이 런타임 에러는 상속이나 소유관계에 상관없이 매우 광범위한 케이스에서 작동하는 듯 하다.


내 경우에는 객체가 네트워크 커넥션 객체를 추상 인터페이스로 소유하고 있는데,

(네트워크라는 것이 TCP, UDP, IPC, BT, Zigbee, UART 등 다양하니까...)

네트워크 추상 인터페이스의 Close() 함수를 소멸자에서 호출하기 때문에 발생했었다.


헛웃음이 나올 뿐 ... 허허


어떤 쓰레드에서는 리눅스에서는 이상 없는데

Mac OS X에서만 위 에러가 발생한다는 글이 있어 확인해볼 문제라고 생각한다.

뭐, 덕분에 큰 단위의 리팩토링이 불가피할 듯 ㅋ

#20151201-02 :: C++ :: mongoose web server에서 mg_enable_multithreading 사용

mongoose web server에서 mg_enable_multithreading 함수를 사용하려고 하면

해당 함수에 대한 링크 에러를 만나게 된다.

이유는 MG_ENABLE_THREADS 플래그가 define 되어있지 않기 때문이다.

컴파일 옵션에 위 플래그를 추가해 준다.

ex) POSIX: -DMG_ENABLE_THREADS

#20151201-01 :: C++ :: build cppcsp2-2.0.6 on Mac OS X

Mac OS X 10.11.1 El Capitan

LLVM 7.0.0 (clang-700.1.76)


홈페이지 [다운로드]


cppcsp2-2.0.6을 Mac OS X에서 빌드하려면 수 많은 에러를 만나게 된다.

아래와 같은 방법을 통해 문제를 해결한다.


소스파일을 다운로드 받고 압축을 푼다.

$ cd ~/Downloads

$ tar -vxzf cppcsp2-2.0.6.tar.gz


Makefile 생성을 위해 아래와 같이 스크립트를 실행한다.

$ ./configure


이 상태에서 make를 컴파일 실행하면 에러가 발생한다.


Makefile에 _XOPEN_SOURCE 선언을 추가한다.

$ vi Makefile


   DEFS = … -D_XOPEN_SOURCE


다시 make를 실행해 보지만 또 컴파일 에러가 발생한다.


src/process.h 파일을 수정한다.

$ vi src/process.h


   typedef ucontext Context;       (수정 전)

   typedef ucontext_t Context;    (수정 후)


다시 make 파일을 실행하면 컴파일 에러는 끝나지 않았다.


src/channel_factory.h 파일을 수정한다.

$ vi src/channel_factory.h


:210

deleteAll(o2o);                                                (수정 전)

StandardChannelFactory::deleteAll(o2o);    (수정 후)


이번에는 make를 실행하면 이번에는 링크 에러가 발생한다.


Makefile에서 -lrt 옵션을 제거한다.

$ vi Makefile


   CPPCSP_LINK_LIBS = -ltr -lpthread    (수정 전)

   CPPCSP_LINK_LIBS = -lpthread          (수정 후)


이제 make를 실행하면 성공한다.

make test를 실행하면 유닛테스트 결과를 볼 수 있다.



#20150127-01 :: eclipse :: GC overhead limit exceeded

eclipse에 새로운 안드로이드 프로젝트를 임포트 하고 실행을 했더니

"GC overhead limit exceeded" 에러가 발생하면서 엉망진창이 되었습니다.


이유는 이클립스에서 JVM 구동에 필요한 메모리에 제한이 걸려있기 때문입니다.

아래와 같이 메모리를 늘려줍니다.


$ vi /work/apps/eclipse/eclipse/eclipse.ini

...

-XX:MaxPermSize=1024m
-Xms512m
-Xmx1024m




#20150126-01 :: eclipse :: eclipse를 ubuntu launcher에 등록하기

우분투 12.04에 이클립스를 설치 한 후 런처에 바로가기를 등록하려고 합니다.

먼저 아래와 같은 내용을 작성합니다.


$ vi /work/apps/eclipse/eclipse.descktop

[Desktop Entry]
Type=Application
Name=Eclipse
Comment=Eclipse Integrated Development Environment
Icon=/work/apps/eclipse/eclipse/icon.xpm
Exec=/work/apps/eclipse/eclipse/eclipse
Terminal=false
Categories=Development;IDE;Java;
StartupWMClass=Eclipse


아래의 위치에 작성한 파일을 심볼릭 링크로 연결합니다.

$ cd ~/.local/share/applications

$ ln -s /work/apps/eclipse/eclipse.desktop eclipse.desktop


아래의 명령을 치면 폴더가 열립니다.

$  nautilus ~/.local/share/applications


폴더에 있는 eclipse.desktop 파일을 런청에 드래그&드랍 하면

런처에 바로가기 등록 됩니다.



#20150119-03 :: go :: go를 이용한 TCP/IP Echo Server Example

아래는 go를 이용한 간단한 TCP/IP Echo Server 예제 입니다.

관리 용이성을 위해 서버와 클라이언트를 한 코드에 넣었습니다.


package main


import (

  "bufio"

  "fmt"

  "net"

  "os"

  "time"

)


func main() {


  send := make(chan string)

  quit := make(chan string)


  addr, err := net.ResolveTCPAddr("tcp", ":9000")


  ln, err := net.ListenTCP("tcp", addr)

  if err != nil {

    fmt.Println(err.Error())

    return;

  }


  go runServer(ln, quit)


  time.Sleep(time.Duration(1) * time.Second)


  conn, err := net.Dial("tcp", "127.0.0.1:9000")

  if err != nil {

    fmt.Println(err.Error())

    return;

  }


  go runClient(conn, quit)

  go runScan(send, quit)


  stop := false

  for !stop {


    fmt.Println("main loop ...")


    select {

    case text, ok := <- send:

      if !ok {

        ln.Close()

        conn.Close()

        stop = true

      }

      conn.Write([]byte(text))

    case err := <- quit:

      fmt.Println(err)

      stop = true

    }

  }


  fmt.Println("complete.")

}


func runScan(send chan string, quit chan string) {


  fmt.Println("runScan begin.")


  scanner := bufio.NewScanner(os.Stdin)

  for scanner.Scan() {

    text := scanner.Text()

    if text == "." {

      close(send)

      break

    }


    send <- text

  }

  

  fmt.Println("runScan end.")

}


func runServer(ln *net.TCPListener, quit chan string) {


  fmt.Println("runServer begin.")


  for {

    conn, err := ln.Accept()

    if err != nil {

      quit <- err.Error()

      break

    }


    go runSession(conn, quit)

  }


  fmt.Println("runServer end.")

}


func runSession(conn net.Conn, quit chan string) {


  fmt.Println("runSession begin.")


  buf := make([]byte, 1024)


  for {

    size, err := conn.Read(buf)

    if err != nil || size == 0 {

      quit <- err.Error()

      break

    }


    _, err = conn.Write(buf[:size])

    if err != nil {

      quit <- err.Error()

      break

    }

  }


  fmt.Println("runSession end.")

}


func runClient(conn net.Conn, quit chan string) {


  fmt.Println("runClient begin.")


  buf := make([]byte, 1024)


  for {

    size, err := conn.Read(buf)

    if err != nil {

      quit <- err.Error()

      break

    }


    fmt.Println(string(buf[:size]))

  }


  fmt.Println("runClient end.")

}


#20150119-02 :: go :: vim에서 go language 사용하기




pathogen 설치한다. 이 때, curl이 필요하여 설치하여 주었다.


$ cd ~/.vim

$ mkdir -p autoload bundle

$ sudo apt-get install curl

$ cd autoload

$ curl -LSso pathogen.vim https://tpo.pe/pathogen.vim


.vimrc 파일을 만든다.


$ cd ~/

$ vi .vimrc

execute pathogen#infect()
syntax on
filetype plugin indent on


vim-go를 설치한다.


$ cd /work/apps/golang

$ git clone https://github.com/fatih/vim-go.git

$ cd ~/.vim/bundle

$ ln -s /work/apps/golang/vim-go vim-go


mercurial을 설치한다.


$ sudo apt-get install mercurial


vim을 실행한 후 GoInstallBinaries를 실행한다.


$ vi

: GoInstallBinaries


자동 완성을 위해 YCM을 설치한다. YCM을 위해서는 python-dev와 cmake가 필요하다.


$ sudo apt-get install python-dev cmake

$ cd /work/apps/vim

$ git clone https://github.com/Valloric/YouCompleteMe.git

$ cd ~/.vim/bundle

$ ln -s /work/apps/vim/YouCompleteMe YouCompleteMe

$ cd YouCompleteMe

$ git submodule update --init --recursive

$ sudo apt-get install build-essential

$ pushd /work/apps/vim/YouCompleteMe YouCompleteMe

$ ./install.sh

$ popd


Tagbar를 설치한다. ctag가 필요하다. 설치 후 단축키 F8에 매핑한다.


$ sudo apt-get install ctags

$ cd /work/apps/vim

$ git clone https://github.com/majutsushi/tagbar.git

$ cd ~/.vim/bundle

$ ln -s /work/apps/vim/tagbar tagbar

$ vi ~/.vimrc

nmap <F8> :TagbarToggle<CR>


파일 브라우저 nerdtree를 설치한다.


$ cd /work/apps/vim

$ git clone https://github.com/scrooloose/nerdtree.git

$ cd ~/.vim/bundle

$ ln -s /work/apps/vim/nerdtree nerdtree

$ vi ~/.vimrc

nmap <C-n> :NERDTreeToggle<CR>


모두 설치하고 vi를 실행시키면 아래와 같은 에러가 발생한다.

YouCompleteMe unavailable: requires Vim 7.3.584+

vi는 정상 동작을 하지만, YCM은 사용할 수 없다.

그래서 vim을 강제로 판올림 해줘야 한다.


$ sudo add-apt-repository ppa:nmi/vim-snapshots

$ sudo apt-get update; sudo apt-get install vim


vi를 원래 버전으로 되돌리려면 아래와 같은 명령을 사용한다.


$ sudo apt-get install ppa-purge; sudo ppa-purge ppa:nmi/vim-snapshots

#20150119-01 :: go :: 우분투에서 go language 설치하기

$ cd /work/apps

$ mkdir golang

$ cd golang

$ wget https://storage.googleapis.com/golang/go1.4.1.linux-amd64.tar.gz

$ tar -C ./ -xzf go1.4.1.linux-amd64.tar.gz


$ cd /work/workbench

$ mkdir golang

$ cd golang

$ mkdir bin pkg src


$ cd ~/

$ vi .bashrc

# go

export GOROOT=/work/apps/golang/golang

export PATH=$PATH:$GOROOT/bin
export GOPATH=/work/workbench/golang
export PATH=$PATH:$GOPATH/bin

$ source .bashrc


#20150116-03 :: ubuntu :: Android Studio 런처에 고정하기

안드로이드 스튜디오를 실행합니다.

상단 메뉴에서 아래의 명령을 실행합니다.


Tools → Create Desktop Entry...


런처에 있는 안드로이드 스튜디오 아이콘에서 마우스 오른쪽 버튼을 누른 후

'런처에 고정' 메뉴를 클릭합니다.