Edge(엣지) 브라우저에서 한국어도 영어도 아닌 다른 언어로 페이지가 열릴 때

이전에도 종종 한국어 또는 영문페이지가 멀정하게 뜨다가 엉뚱하게 일본어로 뜨는 경우가있었다. 그냥 종종 그랬기때문에 불편해도 넘어갔지만 오늘은 좀 자세하게 알아봤다. (만약 외국 사이트에서 한국어로 뜨다가 일본어가 뜬다면 그 페이지는 한국어 번역이 되어있지않지만 일본어로는 번역되어진 페이지이다.)

만약 일본 홈페이지도아닌데 영어도, 한국어도 아닌 일본어 등 다른 언어로 뜬다면 아래처럼 언어가 추가되어있는 경우라고 본다.

2016-10-19-2

이것이 연관되어 엣지에서 아래처럼 브라우저의 언어정보가 한국어와 일본어 동일한 가중치로 전송된다.

2016-10-19-4

Continue reading Edge(엣지) 브라우저에서 한국어도 영어도 아닌 다른 언어로 페이지가 열릴 때

닷넷 Any CPU 빌드한 바이너리가 64비트 OS에서 32비트로 동작할 때

닷넷으로 Text to Speech. 즉 입력 된 텍스트를 읽어주는 TTS를 해달라는 부탁으로 시작하게 된 삽질.

내가 사용하는 OS는 윈도 10이고 타겟은 윈도 7이였다. 윈도 TTS는 https://msdn.microsoft.com/en-us/library/hh361572(v=office.14).aspx 이곳에서 Runtime, Language Packs 두가지를 설치하면 된다고 되어있는데… 이상하게 아무리 재설치를해도 한글 음성이 지원되는 Voice 객체가 나타나지않았다.

윈도 제어판에서는 한글 음성이 나타나는데 닷넷에선 아무리 해도 나타나지않아 포기하고 C++로 Voice 객체를 조회해보았지만 역시나 실패. 혹시나해서 64비트로 빌드하여 다시 조회하니 Heami가 나타나는 것이였다.

그런것이였다. 윈 10은 32비트, 64비트 둘 다 한글 Voice가 재공되는 것이였다… 근데?! 뭐지? 싶어 닷넷 실행파일 띄워놓고 작업관리자 열어보니 32비트로 실행되고있고, 구글링해보니 http://stackoverflow.com/a/23351613 이 댓글이 나왔고, 프로젝트 속성을 보니 아래 옵션이 있었다.

2016-10-16-1

32비트 기본 사용…!!! 32비트 기본이라니! 하.하!? VS2015에서 기본으로 체크되는 옵션인지 어떤지는 모르겠지만 회사에서 VS2015가 나오자마자 구입하였는데… 왠지 최근 만든 닷넷 어플들 32비트 모드로 동작하고있을거같다.

아마도 ActiveX라던지 COM Object, 기타 외부 네이티브 라이브러리가 32비트가 대다수라 생기는 문제가 많기때문에 이런걸 기본옵션으로 체크되어있는거같은데… 나같은 경우엔 그 반대라서 하루 삽질을 하였다.

아… 해결되어서 좋긴한데 왜 눈물이 나려하지… 내 시간은..

Continue reading 닷넷 Any CPU 빌드한 바이너리가 64비트 OS에서 32비트로 동작할 때

shared_ptr 객체를 멀티스레드에서 사용할 때

분명 shared_ptr은 레퍼런스 카운트가 스레드 안정적이라고 되어있다고 나와있지만 아래와같은 코드를 실행하면 실행하자마자 에러가 발생한다.

#include <memory>

std::shared_ptr<int> g;

DWORD WINAPI U(void *)
{
    while (true)
    {
        std::shared_ptr<int> data = g;
    }
    return 0;
}

DWORD WINAPI C(void *)
{
    while (true)
    {
        std::shared_ptr<int> data = std::make_shared<int>(0);

        g = data;
    }
    return 0;
}

int main()
{
    HANDLE h1 = CreateThread(NULL, 0, U, NULL, 0, NULL);
    HANDLE h2 = CreateThread(NULL, 0, C, NULL, 0, NULL);

    WaitForSingleObject(h1, -1);
    WaitForSingleObject(h2, -1);

    return 0;
}

거의 수시간동안 구글링해도 한결같이 나오는건 레퍼런스 카운트는 스레드 안전하다는 것 정도.
그래도 다행이도 계속 검색해보니 결국 아래와같이 atomic을 사용하는 코드가 나왔다.

#include <atomic>
#include <memory>

std::shared_ptr<int> g;

DWORD WINAPI U(void *)
{
    while (true)
    {
        std::shared_ptr<int> data = std::atomic_load(&g);
    }
    return 0;
}

DWORD WINAPI C(void *)
{
    while (true)
    {
        std::shared_ptr<int> data = std::make_shared<int>(0);
        std::atomic_store(&g, data);
    }
    return 0;
}

int main()
{
    HANDLE h1 = CreateThread(NULL, 0, U, NULL, 0, NULL);
    HANDLE h2 = CreateThread(NULL, 0, C, NULL, 0, NULL);

    WaitForSingleObject(h1, -1);
    WaitForSingleObject(h2, -1);

    return 0;
}

저렇게 atomic_store, atomic_load를 사용하니 이제 정상적으로 shared_ptr 객체가 두 스레드간의 참조가 문제없이 되었다. 분명 부스트의 shared_ptr 기준으로 코드를 보면 InterlockedIncrement 함수를 사용하여 카운트하던데 그마저도 저런식으로 사용하니 0xDDDDDDDD로 채워진 이미 초기화 된 변수가 나타났다. 좀처럼 이해하기 힘든 동작이였다.

수시간, 그리고 며칠동안 구글링 아무리 해봐도 shared_ptr는 참조 카운트가 스레드 안전하다고 할 뿐 좀 더 자세한 내용 잘 나오지도않고(…) 그냥 이렇게 사용해야 정말 안전하다 정도로 알고 넘어가야겠다 -_-;;;

shared_ptr 객체를 멀티스레드에서 사용할 때 의문점

ByteBuffer 클래스를 만들고 매소드 get, size 선언. private 맴버를 d, s를 두어 아래와같이 구현하였다.

#include <algorithm>

ByteBuffer::ByteBuffer(char *data, int size)
{
    if(size == 0)
    {
        d = nullptr;
        s = 0;
    }
    else if(data == nullptr)
    {
        d = new char[size];
        s = size;
    }
    else
    {
        d = new char[size];
        s = size;

        std::copy(data, data + size, d);
    }
}

ByteBuffer::~ByteBuffer()
{
    delete[] d;
}

char *ByteBuffer::get()
{
    return d;
}

int ByteBuffer::size()
{
    return s;
}

Continue reading shared_ptr 객체를 멀티스레드에서 사용할 때 의문점