증상: 


잘 사용하고 있던 프로젝트가 어느 순간 갑자기 링크 에러로 빌드가 실패했다.


컴파일이 끝난 후 링킹 과정에서 한참 동안 응답이 없기 때문에 문제 파악이 힘들었다.


1>------ 빌드 시작: 프로젝트: XXXXXXXX, 구성: Debug Win32 ------

1>  LINK : F:\XXXX\...\XXXX.exe을(를) 찾을 수 없거나 마지막 증분 링크에 의해 빌드되지 않았습니다. 전체 링크를 수행하고 있습니다.

1>

1>LINK : fatal error LNK1000: Internal error during IMAGE::Pass1

1>

1>    Version 14.00.23918.0

1>

1>    ExceptionCode            = C0000006

1>    ExceptionFlags           = 00000000

1>    ExceptionAddress         = 602FDBE0 (602F0000) "C:\WINDOWS\SYSTEM32\VCRUNTIME140.dll"

1>    NumberParameters         = 00000003

1>    ExceptionInformation[ 0] = 00000000

1>    ExceptionInformation[ 1] = FEA18AEA

1>    ExceptionInformation[ 2] = C0000185

1>

1>  CONTEXT:

1>    Eax    = FEA18B26  Esp    = 0019E790

1>    Ebx    = 0019E7E4  Ebp    = 0019E7B4

1>    Ecx    = 0000003C  Esi    = FEA18AEA

1>    Edx    = 00000001  Edi    = 0019E7E4

1>    Eip    = 602FDBE0  EFlags = 00010202

1>    SegCs  = 00000023  SegDs  = 0000002B

1>    SegSs  = 0000002B  SegEs  = 0000002B

1>    SegFs  = 00000053  SegGs  = 0000002B

1>    Dr0    = 00000000  Dr3    = 00000000

1>    Dr1    = 00000000  Dr6    = 00000000

1>    Dr2    = 00000000  Dr7    = 00000000

========== 빌드: 성공 0, 실패 1, 최신 0, 생략 0 ==========



구글링을 해 보니 한 때 구버전 비주얼스튜디오 자체 버그가 있어서 핫픽스를 통해 해결이 가능했던 것으로 보였다.


그러나 내가 사용하는 환경은 Visual Studio 2015 Community 최신 버전이었기 때문에 별 도움이 안 됐다.


다음과 같이 관련된 몇 개의 글이 있었지만 문제를 해결할 수 없었다.


https://github.com/nanomsg/nanomsg/issues/472


https://support.microsoft.com/en-us/kb/826326


같은 프로젝트를 Visual Studio 2010으로 빌드해보아도 동일한 실패 현상을 겪었다.





해결:


해당 프로젝트는 OpenCV를 사용하는 프로젝트였는데, 추가 라이브러리로 지정된 OpenCV 경로가 다른 하드디스크(E:\)로 되어있었다.


나중에 알고보니 하드디스크 케이블에 문제가 생겨서 읽기/쓰기가 정상적으로 이루어지지 않고 있었다.


때문에 링커에서 라이브러리에 연결을 시도해도 디스크가 응답하지 않아서 에러가 생겼던 것이다.


하드디스크 케이블을 다른 것으로 교체한 후 디스크 작동이 정상적으로 이루어지는 것을 확인한 다음 다시 빌드를 시도했더니


LNK1000 링크 에러가 생기던 문제가 말끔히 해결되었다.

Posted by Kugi
,



요약: 앱 차단으로 인해 실행을 못하는 경우가 발생했는데 인터넷에 떠도는 해결방법 중 관리자 권한 변경과 관련된("net user administrator /active:yes" 등) 방법이 그다지 마음에 안들던 차에 다른 해결방법을 찾아서 본 포스트를 작성하게 되었습니다. 관리자권한 콘솔에서 프로그램을 실행하면 됩니다.



* * * * * * * * * *



한컴2014를 사용하는데 자꾸 문서를 열 때 상위 버전에서 작성된 문서라는 메시지가 떴다. 생각해보니 업데이트를 안한지 꽤 된 것 같았다.



그래서 업데이트 프로그램을 수동으로 실행하려고 했는데 다음과 같이 앱이 차단되었다는 경고창이 떴다.


마우스 오른쪽 버튼을 클릭하여 "관리자 권한으로 실행"을 선택해도 마찬가지였다.


"이 앱은 사용자 보호를 위해 차단되었습니다."

"This application has been blocked for your protection"


이 이미지는 구글 이미지검색에서 가져온 것이다.

필자가 이 창을 다시 띄우려고 했지만 이미 문제를 해결해버려서 다시 볼 수 없었다.


메시지 창의 제목이 사용자 계정 컨트롤이라고 되어있지만 아마 제어판에 있는 계정 컨트롤 설정과는 무관할 것이라고 생각했다. 


참고로 계정 컨트롤 설정은 다음과 같이 되어있다.



인터넷 검색을 해 보니 누군가가 이미 계정 컨트롤을 끄고 시도했으나 역시나 실패했다는 글이 있었다.


다음으로 찾은 방법은 관리자 계정(관리자 권한이 부여된 사용자 계정이 아닌 "Administrator" 계정)을 활성화시켜서 사용하는 방법이다.


보안상 문제도 있고 로그오프도 해야되는게 별로 마음에 안 들었다.


그러던 차에 한번 시도해본 방법이 관리자 콘솔을 열어서 프로그램을 실행하는 것이었는데, 결과 정상적으로 실행이 되었고, 이후로는 해당 프로그램에 대해서 같은 현상이 나타나지 않았다.


다음은 컴퓨터에 익숙하지 않은 사람들을 위한 좀 더 자세한 설명이다.


Solution:


1. 탐색기로 프로그램의 실행파일(.exe)이 위치한 폴더를 연다. 바로가기 아이콘이라면 탐색기에서 마우스 오른쪽 버튼을 클릭-속성 창을 열어서 "파일 위치 열기"를 누르면 된다.  시작메뉴의 아이콘이라면 마우스 오른쪽 버튼을 클릭하여 "파일 위치 열기"를 먼저 한번 더 해야 한다.








2. 해당 폴더 경로에서 관리자 권한 콘솔을 연다.


탐색기 상단 메뉴의 [파일] - [명령 프롬프트 열기] - [관리자 권한으로 명령 프롬프트 열기]를 선택하면 된다.




3. 콘솔에 프로그램 이름을 입력하여 실행한다.


참고로 아래 이미지에서는 폴더내에 보이는 실행 파일 이름이 업데이트 후 HncUpdate90.exe로 바뀌었으나 원래는 HncUpdate.exe였다.




Posted by Kugi
,



OpenCV3.0.0 정적 라이브러리(Static Library)를 사용하도록 하여 release 모드로 빌드한 영상처리 어플리케이션을 내 컴퓨터가 아닌 다른 PC에서 테스트해봤는데


프로그램 실행까지는 정상적으로 되었는데 비디오 파일(.mp4)을 열려고 하면 실패하였다. 파일 경로의 문제는 아니었는데 코덱 문제일까 싶어서 좀 찾아봤더니

(http://answers.opencv.org/question/56519/opencv-24-static-lib-relies-on-opencv_ffmpegdll-on-windows/)


FFMPEG 라이브러리 때문에 생기는 문제였다.


FFMPEG 라이브러리는 GPL 라이선스를 적용받기 때문에 이 라이브러리를 정적으로 포함하도록 빌드할 경우 모든 소스코드가 똑같이 GPL 라이선스를 적용받아야 한다.


때문에 BSD 라이선스를 적용한 OpenCV는 이 FFMPEG 라이브러리를 동적으로 연결해서 사용하도록(DLL) 되어있다.


즉, 내가 다른 PC에서 테스트할 때 FFMPEG 라이브러리는 설치하지 않았기 때문에 비디오 파일을 열 때 실패하게 된 것이다.


release 된 .exe 파일과 같은 경로에 opencv_ffmpeg300.dll 파일을 넣어주었더니 제대로 비디오 파일을 여는 데 성공했다.


opencv_ffmpeg300.dll 파일은 다음과 같이 OpenCV bin 폴더 내에 들어있다.






참고로 OpenCV를 정적으로 빌드하기 위해서는 추가 종속성(Additional Dependencies)에 OpenCV의 staticlib 내의 라이브러리 파일들 뿐만 아니라


다음과 같은 추가적인 라이브러리 파일 입력이 필요하다. (x86 시스템 기반 기준)

 - comctl32.lib

 - vfw32.lib



개발환경은 Windows 8.1 Pro K, Visual Studio 2013 Professional 이며 C++를 사용했다.

테스트했던 PC는 Windows 7 Enterprise이다.



나중에 편리하게 사용하기 위해 전체 입력을 여기에 기록했다.

comctl32.lib

vfw32.lib

IlmImf.lib

ippicvmt.lib

libjasper.lib

libjpeg.lib

libpng.lib

libtiff.lib

libwebp.lib

opencv_calib3d300.lib

opencv_core300.lib

opencv_features2d300.lib

opencv_flann300.lib

opencv_hal300.lib

opencv_highgui300.lib

opencv_imgcodecs300.lib

opencv_imgproc300.lib

opencv_ml300.lib

opencv_objdetect300.lib

opencv_photo300.lib

opencv_shape300.lib

opencv_stitching300.lib

opencv_superres300.lib

opencv_ts300.lib

opencv_video300.lib

opencv_videoio300.lib

opencv_videostab300.lib

zlib.lib


Posted by Kugi
,



  C++를 이용해 OPENCV 등의 오픈 소스 라이브러리를 사용하거나, CMake를 이용해서 범용 프로젝트를 빌드하거나 할 때면 다음과 같은 소스코드 파일 확장자들을 볼 수 있다.

  • .c
  • .h
  • .cc
  • .cpp
  • .c++
  • .cxx
  • .hpp
  • .hxx
  • .hh
  • .h++
  • .H


  일반적으로 C++ 언어를 처음 익히게 되면 선언을 구현한 헤더파일은 .h 확장자를 달고, 정의를 구현한 소스파일은 .cpp 확장자를 다는 것이라고 배운다. C++가 아닌 C에서는 .cpp 대신에 .c 확장자를 쓴다는 것도 알고 있을 것이다. 그래서 위 확장자들 중 이 세 개를 제외한 나머지 생소한 확장자들을 접하게 되면 도대체 무슨 용도인지 몰라 지레 겁을 먹는 경우가 많다. 그러나 다행스럽게도 이 파일들은 모두 우리가 알고있는 그 C++ 문법을 따르고 있다. 예를들어 VC++(비쥬얼 스튜디오 C++ 컴파일러)에서 .cpp 확장자와 .cxx 확장자는 똑같은 의미이다. 단지 여러 개발 환경에서 쓰이게 되면서 이처럼 다양한 형태의 확장자로 나뉘게 된 것 뿐이다. 확장자라는게 단지 파일의 용도를 쉽게 구별하기 위한 용도로 쓰이는 것이기 때문에 내용만 올바르다면 사실상 전혀 처음보는 확장자를 달더라도 문제는 되지 않는다.


  본래 처음 C++가 만들어졌을 때, 파일 확장자는 .c++를 사용하도록 되어있었다. 그런데 특정 OS(운영체제)에서는 확장자이름에 '+'를 사용할 수 없었기 때문에 '+' 대신에 'x'를 넣어 .cxx라고 쓴 것이다. 눈치 챈 사람도 있겠지만 'x'를 사용한 이유는 '+'를 옆으로 살짝 돌려 놓은 것처럼 생겼기 때문이다. MS-DOS와 MS-Windows에서는 .cpp를 사용하였는데 현재는 이것이 거의 표준처럼 되어있다. 관례적으로 파일 확장자 이름이 .c나 .h가 변형된 것 처럼 생긴 확장자라면 C++ 문법이 적용됬음을 의미한다고 보면 된다. 또한 iostream, vector 처럼 확장자를 표시하지 않는 스타일도 있다.


  그런데 .hpp 또는 .hxx 확장자는 왜 굳이 사용했을까? 일반적으로는 C++에서도 헤더파일의 확장자 이름은 C에서처럼 .h를 사용한다. 다만 C++ 문법중에는 정의와 선언을 분리하기 어려운 상황이 몇 가지 있다. 그 중 한가지가 바로 템플릿(template)을 구현할 때이다. 템플릿의 타입이 컴파일시간에 지정되므로 헤더파일에 정의가 구현되어야 한다. 그래서 이런 경우에는 특별히 C++ 문법을 썼음을 확실히 명시하기 위해 .hpp, h++, .hxx 등을 사용하는 것이다. 템플릿 정의의 경우 .txx, .tpp, .tpl이라고 표시하기도 한다. 인라인 함수 정의에는 .ii, .ixx, .ipp, .inl을 쓰기도 한다.


  확장자는 아니지만 다른 예도 있다. makefile 매크로에서는 다음과 같은 의미로 사용한다.

  • CPPFLAGS : 전처리기(Pre-Processor) 플래그
  • CFLAGS : C 컴파일러(Compiler) 플래그
  • CXXFLAGS : C++ 컴파일러 플래그
  • LDFLAGS : 링커(Linker) 플래그
  • CC : C 컴파일러 경로
  • CPP : 전처리기 경로
  • CXX : C++ 컴파일러 경로
  • LD : 링커 경로



참고: http://forums.codeguru.com/showthread.php?397010-What-s-with-*.cxx-files-instead-of-*.cpp

Posted by Kugi
,



Problem: 

11-13 15:08:17.982: E/dalvikvm(6149): dlopen("/data/app-lib/com.kugistory-1/libkugistory.so") failed: dlopen failed: cannot locate symbol "rand" referenced by "libkugistory.so"...

11-13 15:08:17.982: W/dalvikvm(6149): Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/kugistory/NativeImageProcessor;

11-13 15:08:17.982: D/AndroidRuntime(6149): Shutting down VM

11-13 15:08:17.982: W/dalvikvm(6149): threadid=1: thread exiting with uncaught exception (group=0x41b10ba8)

11-13 15:08:17.992: E/AndroidRuntime(6149): FATAL EXCEPTION: main

11-13 15:08:17.992: E/AndroidRuntime(6149): Process: com.kugistory, PID: 6149

11-13 15:08:17.992: E/AndroidRuntime(6149): java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "rand" referenced by "libkugistory.so"...

11-13 15:08:17.992: E/AndroidRuntime(6149): at java.lang.Runtime.loadLibrary(Runtime.java:364)

11-13 15:08:17.992: E/AndroidRuntime(6149): at java.lang.System.loadLibrary(System.java:526)

11-13 15:08:17.992: E/AndroidRuntime(6149): at com.kugistory.NativeImageProcessor.<clinit>(NativeImageProcessor.java:8)


안드로이드 네이티브(native) 라이브러리를 사용하려다가 위와같은 에러가 생겼다.


찾아보니 ndk-r10의 버그인 듯 하다.


다음과 같은 어떤 사람의 말로는 32-bit, 64-bit 빌드 타입과 관련된 문제인 듯 하다.

You need to use the 32-bit NDK (android-ndk32-r10b-darwin-x86_64) if building for 32-bit targets.

In the ARM headers in the 32-bit target NDK, rand() is declared as a static inline function (and as such does not need to exist as a symbol in libc.so on ARM devices).

In the ARM headers in the 64-bit target NDK, rand() is declared as a regular function, but since it does not exist in the libc.so on ARM devices, there is a runtime error.

Ergo, use the 32-bit target NDK when targeting 32-bit platforms. Or tell Google that their shit is broken.



Trials:

이것을 stl static 라이브러리에서 shared 라이브러리 이용으로 바꾸면 된다는 말을 지나가다가 보고는 다음과 같이 시도했으나 실패했다.







Solution:


해결 방법을 찾는것은 매우 힘들었지만, 해결 방법 자체는 간단했다.


다음과 같이 Application.mk에서 대상 OS들을 몇가지 더 추가하자 거짓말처럼 문제가 풀렸다.


APP_STL := gnustl_static

APP_CPPFLAGS := -frtti -fexceptions

APP_ABI := armeabi armeabi-v7a x86 mips # arm64-v8a x86_64 mips64

APP_PLATFORM := android-16

APP_OPTIM := release

NDK_TOOLCHAIN_VERSION := 4.8



참고로 Android.mk는 다음과 같이 설정해둔 상태였다.

OpenCV를 위한 설정 등 없어도 되는 줄들도 포함되어 있다.

LOCAL_PATH := $(call my-dir)


include $(CLEAR_VARS)


OPENCV_INSTALL_MODULES:= on

OPENCV_CAMERA_MODULES:= off

OPENCV_LIB_TYPE:= STATIC


include E:\OpenCV-2.4.9-android-sdk\sdk\native\jni\OpenCV.mk


LOCAL_MODULE    := Kugistory


FILE_LIST := $(wildcard $(LOCAL_PATH)/*.cpp)

LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%) 

LOCAL_C_INCLUDES += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/include

LOCAL_C_INCLUDES += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include

LOCAL_C_INCLUDES += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a-hard/include

LOCAL_LDLIBS += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/libgnustl_static.a

LOCAL_LDLIBS +=  -llog -ldl -lz


include $(BUILD_SHARED_LIBRARY)


Posted by Kugi
,