win7 - Visual C++ 6.0호환성 문제.

akayong의 이미지

프로그램 하나를 분석 중에 있습니다.

먼저 저는.. 첫 사회생활을 시작한 후
리눅스와 FreeBSD에서만 코딩을 하다가

작년에 이직 후, 처음 윈도우 환경에서 코딩을 하게 되었습니다.
(더군다나 작년부터 올해 초 까지는 웹 개발만 담당)

그러다 최근에 A라는 회사에서 예전에 저희 회사에 납품을 한 프로그램을 좀 분석 하게 되었는데요.

이게 개발한지 좀 된 프로그램이라 개발환경이 Visual C++ 6.0 입니다. (개발 언어도 C++)
제 PC OS는 win7 이구요.

일단 갖고 있는 소스를 그대로 구동 해 보면 프로그램이 정상적으로 잘 돌아갑니다.

그런데 제가 무슨 작업을 하려고 소스에 조금 손을 대고 프로그램을 실행 해 보면
항상 에러가 납니다.

이것가지고 거의 1주일을.. 잡고 있는데요.. 해결책이 안나옵니다.. 구글링 해봐도 원인을 못찾겠구요.

먼저 제가 테스트한 상황을 말씀드리면

한 헤더 파일에
static void test();
라고 선언을 해 주고

해당 헤더파일을 include 한 소스 파일에
void test() {};
이렇게 그냥 빈 함수를 정의 해 주어도

프로그램이 실행이 안됩니다.

디버깅 해보면
특정 위치에서
Unhandled exception in XXXX.exe (NTDLL.DLL) : 0xC0000005 : Access Violation
이라고 나옵니다.

이 메세지가 나오는 곳은
VERIFY(::GetModuleFileName()) 입니다.

VERIFY()는 MFC의 afx.h 에 정의 되어 있는 함수. (MFC API)
GetModuleFileName() 도 MFC API 입니다.

그래서, A라는 회사의 담당자에게 문의 해 봤더니
VIsual C++ 6.0 과 Win 7 이 호환성이 잘 맞지 않아
그렇게 나오는거 같다는 답변을 받았고.
그부분은 자기도 해결책을 모르겠다..? 라고 연락을 받았습니다.

저도 예전에 어디선가 Win7과 Visual C++ 6.0 과의 호환성이 잘 맞지 않는다는 이야기를 들어본 것 같아.

그럴거라고 추측은 하고 있는데.

혹시, 이와 비슷한 현상을 겪어 보셨거나.
어느 부분을 살펴 보면 될것 같은지 알고 계신분은
뭐라도 좀 던져 주시면 감사하겠습니다.

어느 부분을 어떻게 살펴 봐야 할지..
도저히 감이 안오네요.. ㅠㅠ

익명 사용자의 이미지

뜬금없이 VC++ 6.0가 눈에 띄길래 왜 또 2000년대 초반 쓰레드가 끌려올라왔나 해서 봤는데 새 글이네요 -_-;

VC++ 6.0은 Win Vista 이후 이미 지원이 끊겼습니다. 제 기억으로는 언제쯤부터 아예 설치조차 정상적으로 되지 않았던 것 같은데, 어찌어찌 편법으로 설치하는 분들도 계시더라고요.
어쨌든 지원이 끊긴 것은 끊긴 것이고, 어디 가서 하소연해 봤자 소용 없습니다. 사실 제 기억으로는 VC++ 6.0은 STL에도 버그가 있는 등 여러가지로 문제가 많았어요.

VC++ 6.0 시절의 레거시 코드를 갖고 계신다면, 음, 유감이겠습니다만, 일단 VS6 Service Pack 6부터 한 번 설치해보세요.

https://www.microsoft.com/ko-kr/download/details.aspx?id=9183

해결될 수도 있고 안 될 수도 있습니다. 그래도 안 된다면, 방법은 두 개 뿐입니다.

1. 해당 소스 코드를 최신 개발환경에 맞게 재작성하거나(상당한 인력과 시간이 투입되어야겠죠)
2. 어떻게든 문제를 찾아 해결해야지요. 문제가 소스코드에 있을 수도 있고, VC++6.0에 내장된 라이브러리에 있을 수도 있습니다. 그 경우 바이나리만 가지고 디버그를 해야 할 수도 있어요.

akayong의 이미지

win7에 VC6++ 을 설치 할때는 아무 오류 없이 정상적으로 잘 설치가 되더라구요..

실제 이 프로그램을 당장 사용하거나 할건 아니라, 재작성 하는건.. 안해도 될것 같구요.. (분석이 목적이라)

이게 웃긴게.. 같은 win7에 VC6++ 임에도 불구하고,
어떤 자리에선 되고 어떤 자리에선 안되는.. 기이한 현상이 있는거죠..
이게 아마 호환성 등의 문제가 있는게 아닐까 싶습니다.

무튼 디버깅이 답인거겠네요.. 감사합니다.

36311의 이미지

MFC가 일반적인 라이브러리, 그러니까 모듈화 되어 있어서 밖에서는 부르기만 하면 되는 라이브러리가 아니라
자기가 메인 코드를 다시 호출하기도 하는 등의 복잡한 특성이 있었던 거 같습니다.(기억이 정확하지 않은점 사과드립니다;;;)

그래서 헤더 파일에 그냥 넣으시지 마시고 MFC를 부르는 Main이 시작되는(이것도 기억이 정확하지 않은점 사과드립니다;;; 무엇인지 아시리라 믿습니다;;;)
전후 부분 혹은 그 안에 한번 넣어서 시험해보시면 어떨까 하는 부정확한 제안을 한번 드려봅니다.

* 포럼 주제와 무관한 신변잡기를 반복해서 올리지 맙시다.
* 질문 게시판 만이라도 익명 글쓰기를 막아야 한다고 생각합니다.

akayong의 이미지

제가 윈도우 개발 및 MFC 프로그램 이 처음이라..
MFC 라이브러리 관련해서 공부를 좀 해야 할 것 같습니다.
MFC만의 특성이 있는듯 하네요.
감사합니다.

라스코니의 이미지

제가 문법이 좀 약해서,,, 그런데 왜 헤더 파일에 static void test(); 으로 static 을 붙이셨죠?
그냥 void test(); 로 해보세요.

그리고 소스 파일에
void test() {}; 는 전혀 틀린 문법입니다.
void test() { ; }

으로 보세요. 아니면 void test() {} 이나요.

선언이나 함수 block { } 으로 둘러 쌓여지지 않는 ; 는 명백한 문법 오류입니다.

akayong의 이미지

우선
소스에 void test(){}; 요건.. 제가 글 적으면서 무의식중에 쳐버린거고
소스에는 그냥 void test(){} 까지만 있습니다. (순전 테스트용)

그리고 static으로 선언한 이유는
가장 메인이 되는 한 파일에서만 생성 하고.
프로그램 소스 여기저기서 편하게 불러 쓰기 위함입니다.

실제 프로그램 동작에 관련이 된게 아니라
제가 디버깅 하기 편하게 하기 위해
프로그램 조금 테스트 하기 위해서요

라스코니의 이미지

static 함수는 그 인식이 그 소스 파일 스코프 내에서만 제한되는 특징을 지닙니다.
따라서 다른 소스 파일에서 딴 소스 파일에 있는 static 함수를 불러쓰지 못합니다.
그래서 헤더 파일에 static void test(); 라고 하는 것은 실제로는 무의미한 것입니다.

akayong의 이미지

static을 사용 함으로써
데이터 영역에 한번 로드 해 놓고
다른 소스 파일에서는 namespace를 통하여 바로 접근하고자 하여 그렇게 사용 한겁니다.

즉. 그냥 일반 함수로 만들어서
해당 함수를 사용할때 마다 객체를 생성해서 a.test() 형태 호출이 아니라
namespace::test() 로 바로 사용하려고 저렇게 했습니다~

이렇게 하면 무의미 한건가요..?
static으로 안해도 그냥 namespace::test() 가 가능 한가요..?

라스코니의 이미지

C++ 에서 사용하시나 보네요.
C++ 은 잘 모르는데 예제를 잘 찾아보시고 다시 한번 해 보시죠. VC++ 6 이 오래되었지만 일반적인 C++ 구문이 안될리가 없다고 생각됩니다.

익명 사용자의 이미지

대체 무슨 의미로 static을 쓰고 계신 건가요?

제가 아는 한 C++에서 static은 사용되는 맥락에 따라 3가지 의미를 가지고 있습니다.

(1) namespace scope 안의 변수, 함수 또는 함수 템플릿의 이름에 적용하여, 해당 이름에 internal linkage를 지정.
- namespace scope라는 것은 사용자 정의 namespace의 body뿐만 아니라, 소위 global namespace도 포함합니다.
- internal linkage란, 해당 이름을 같은 해석 단위(translation unit) 안의 다른 scope에서도 사용하여 같은 개체(entity)를 얻을 수 있음을 말합니다.
- 즉 internal linkage를 가진 이름은 소스 코드 하나 안에서만 통용되며, 서로 다른 소스 코드 사이에서 공유되지 않습니다.

(2) 지역 변수 선언에 적용하여, 해당 변수가 static storage duration을 가진다는 것을 지정
- 소위 "정적 지역 변수"이며, 해당 변수의 선언이 처음으로 실행될 때 초기화되어 프로그램이 종료될 때까지 계속 존재하게 됩니다.

(3) 클래스 안에서의 멤버 선언에 적용하여, 해당 멤버가 정적 멤버(static member)임을 지정
- 클래스의 정적 멤버는 여전히 클래스의 일부이지만, 각 클래스 인스턴스로부터 독립적인 멤버를 말합니다.

#include <iostream>
using namespace std;
 
namespace N{
	static int A;		// (1), namespace scope
				// 오직 이 소스 코드 안에서만 N::A라는 이름이 이 변수를 가리킵니다.
				// 다른 소스 코드에서는 이 이름으로 이변수 참조 불가
				// 아, 물론, 어떻게든 포인터를 전해받는다던가 하면 당연히 접근 가능하죠.
}
 
static int B;			// (1), namespace scope (이런 경우를 global namespace라고 합니다.)
				// 위와 같습니다.
 
static int f(void)		// (1), 이 이름은 이 소스 코드 안에서만 이 함수를 가리킵니다.
				// 다른 소스 코드에서 f라는 이름으로 이 함수 호출 불가
				// 마찬가지로, 함수 포인터를 넘겨받으면 당연히 그걸론 호출이 되죠.
{
	static int C = 0;	// (2), local variable
				// 이 함수가 처음 호출될 때 변수 C가 초기화될 것입니다.
				// 그 이후 프로그램이 종료될 때까지 계속 살아 있습니다.
	return C++;
}
 
class W{
public:
	static int D;		// (3), class static data member
	static int g(void);	// (3), class static member function
};
 
int W::D = 0;			// class static data member 정의
int W::g(void)			// class static member function 정의
{
	return 0;
}
 
int main(void){
	cout << "&W::D = " << &W::D << endl;
				// class static data member의 사용.
	cout << "W::g() = " << W::g() << endl;
				// class static member function의 호출.
				// 위 두 가지 class static member는 class instance를 만들지 않고도 사용할 수 있었습니다.
				// 내포하는 바가 두 가지인데,
				// (i) class static member function은 "특정 클래스 인스턴스에 대해 호출될 필요가 없고"
				// (ii) class static data member는 "클래스 인스턴스에 속한 데이터 멤버가 아닙니다."
	return 0;
}

질문자님의 글을 볼 때, (2)와 (3)을 혼동하시는 것 같고 (1)에 대해서는 잘 모르시는 것 같네요.
같은 키워드라도 맥락에 따라 의미가 이렇게 다르니 분명히 숙지하시는 게 좋을 듯 합니다.

익명 사용자의 이미지

지금 질문자님이 주신 정보를 두고 판단해 볼 때, 질문자님이 쓰신 static은 (1)의 의미로 해석될 겁니다.

그런데 (1)의 의미를 가지는 static은 일반적으로 헤더 파일에 넣지 않습니다.
조금만 생각해 보면 자명하죠. internal linkage를 가지는 이름은 여러 해석 단위(소스 코드라고 보셔도 무방) 사이에 서로 공유가 되지 않는다는 것을 의미하거든요.
헤더 파일은 보통 여러 소스 코드 사이에 공유되는 정보를 담기 위해 있는 것 아니던가요?

(i) 특히나, 헤더 파일에 (1)의 의미를 가진 변수를 선언해 놓고는, 하나의 변수가 모든 소스 코드 사이에 공유될 거라고 믿는다면 정말로 치명적인 실수를 하시는 겁니다.
그 경우 해당 헤더를 include하는 모든 소스 코드가 각각 자신만의 변수를 만들어 쓰게 됩니다.
심지어 컴파일러는 "프로그래머가 직접 각 소스 코드마다 static이라고 명시해서 internal linkage를 지정했군"이라고 생각해서 거의 경고조차 해 주지 않습니다.
static을 잘 모르는 초보 프로그래머들이 이런 실수를 하면 디버그하기 정말로 어렵습니다. 주소값을 다 찍어 봐야 각기 서로 다른 변수를 쓰고 있다는 게 밝혀지겠지요. 기초 프로그래밍 공부가 이렇게 중요한 건데, 이런 내용 잘 안 가르치더라고요.

(ii) 헤더 파일에 (1)의 의미를 가진 함수를 선언해 놓을 경우, 반드시 그 함수 정의 역시 헤더 파일에 있어야 합니다. 이 경우 그 헤더를 include하는 모든 소스 코드가 해당 함수 본체의 복사본을 가지게 되겠죠. 경우에 따라선 또 이게 괜찮게 돌아가는 경우가 있어요. 어차피 inline 처리될 게 뻔한 조그마한 함수는 이렇게 하는 게 더 나은 경우도 있고요.

36311의 이미지

> 읭?
>
> 대체 무슨 의미로 static을 쓰고 계신 건가요?

익명이라도 예의를 갖춰 씁시다

* 포럼 주제와 무관한 신변잡기를 반복해서 올리지 맙시다.
* 질문 게시판 만이라도 익명 글쓰기를 막아야 한다고 생각합니다.

익명 사용자의 이미지

익명 사용자는 물론 익명이죠. 그런데 36311은 익명이 아닌가요? 귀하의 숫자 닉네임에는 실명은 커녕 메일주소 하나도 안 걸려 있는데요.

질문자님이 C++ 키워드 static를 쓰신 의도가 명확하지 않다는 걸 지적하고, 예제 코드까지 달아 가며 설명해 드린 제 답변이 예의를 잃은 것이라면, 귀하의 예의 있는 답변은 얼마만큼의 성의를 담고 있습니까?

나름 밤늦게 시간 들여 가며 정성들여 쓴 답변이었습니다만, 심히 유감이로군요.
KLDP 질답란에 올라오는 프로그래밍 질문들은 종종 C/C++ 문법의 기묘한 코너 케이스를 다루곤 해서 재미가 있고, 저 나름대로도 읽을 만한 답변을 다는 연습을 하느라 활동하고 있습니다만,
여기서 익명 글쓰기를 막아 버리면 뭐 저는 36312 같은 익명 아이디 하나 만들어서 옮겨 가면 그만입니다.

아니면 뭐, KLDP가 아이핀이나 공인인증서 등을 이용한 실명인증까지 해야 한다고 주장하실 건가요? 그쯤 되면 저도 다시 생각해봐야겠습니다만.

akayong의 이미지

일단 상세한 설명과 예시 감사 드립니다.

제 머리속에 static은 "정적", "데이터영역", "최초 한번만 초기화", "프로그램 종료시 까지 유지" 정도로 머리속에 들어 있었던거 같구요
생각 하신대로 제가 (2)와 (3)을 혼동 하고 있었네요.

그리고 제가 사용하고자 하는 의도는 (3) 이었고..

특정 클래스 인스턴스를 생성후 호출 하지 않고, 바로바로 호출 하려고 사용 했던 것 입니다.

그리고.. 이게 실제 개발용이 아니라 제가 단순히 프로그램을 분석 하기 위해
제 편의를 위해 함수 하나를 추가 해 본건데..
제가 아무 생각없이 그냥 가볍게 쓴 내용에
이리 자세히 설명을 달아 주시니 너무 감사드립니다.

추가로, 저는 저 부분이 예의에 어긋난다고 생각되지는 않습니다.
어떻게 보느냐에 따라, 좀 기분 나쁘게 보일 수 도 있다고 생각 되나
그건 말하는 사람의 의도가 어떠냐, 또 받아들이는 사람이 어떻게 받아들이냐에 따라 다를거 같습니다.

익명 사용자의 이미지

질문자님께서 static을 사용하시는 목적에 대해 말씀하시는 내용이 다소 혼란스러워서, 좀 의아스럽다는 의미의 질문으로 답변을 시작했습니다만.
그 부분에 대해서만 유난히 민감하게 반응하시는 분이 있어서 좀 당혹스러웠습니다.
질문자님께서 크게 개의치 않아 주시니 다행이네요.

어찌되었건, 질문자님께 도움이 될 수 있었다니 기쁩니다.

Necromancer의 이미지

급하시다면 가상머신에 XP 세팅하세요.
VS6.0은 XP까지만 되고 비스타부터는 꼼수 써야 합니다.

Written By the Black Knight of Destruction

akayong의 이미지

여기 회사 개발 환경이..
인터넷 망과 단절이 되어 있어서... (USB 같은것도 막혀 있음)
VMWare나 VirtualBox 같은 그런걸 다운받을 수 도 없고
구했다 치더라도..
XP 이미지도 또 다운을 어떻게 받으며 ㅋㅋㅋ
그렇게 하기도힘들어서요 ㅠㅠ

댓글 달기

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