const char * 형식의 인수를 갖는 함수를 재귀호출하면 문제가 생기는 가요 ?

parkon의 이미지

CERN에서 개발된 ROOT라는 툴킷(라이브러리)를 가지고 작업 중입니다.

제가 짜려고 하는 루틴은
디렉토리 명을 인수를 받아
그 안에 있는 파일들 중, 원하는 데이타 형식을 가진 녀석들을 저의 DB속에 집어 넣는 일인데,
서브 디렉토리들을 가질 수도 있어 재귀적 호출을 해야 하고,
그 중 어떤 파일이나 섭 디렉토리가 zip을 압축되어 있어 zip 확장자를 가진 녀석을 만나면
이들을 임시 디렉토리에 푼 다음 풀어진 파일들도 검색하는 일입니다.

즉 이 루틴을 void foo(const char* path)라고 한다면 대충 구조는 다음과 같습니다.

void foo(const char* path) {
 
   printf("For check 1: %s\n", path); // for check
 
   if (path가 디렉토리 명이 아닌가 ?) return;
   TList *files = (path 밑의 파일이름들에 대한 리스트);
   TSystemFile *file; // 하드디스크 상의 파일 혹은 디렉토리에 대한 클래스 인스턴스의 포인터
   TIter next(files);
   int nzip = 0; // 임시 디렉토리에 압축을 푼 zip 파일 갯수
   while ((file=(TSystemFile*)next())) {
      printf("For check 2: %s\n", path); // for check
 
      if (file의 이름이 "." 혹은 ".."인가?) continue;
      TString fname = Form("%s%s", path, file->GetName()); // path 정보를 포함한 파일 명
      if (fname이 디렉토리 명인가 ?) {
         foo(fname.Data()); // 재귀호출
      } else if (파일확장자가 zip인가?) {
         TString unzip_dir = "/tmp/foo_tmp"; // 실제론 유일한 새 디렉토리를 만들기 위해 좀 복잡함.
         if (nzip == 0) { // 
            압축을 풀 임시 디렉토리 생성 및 확인
         }
         gSystem->Exec(Form("unzip %s -d %s", fname.Data(), unzip_dir.Data())); // 압축 풀기
      } else if (원하는 형식의 데이타 파일인가 ?) {
         do_my_job(fname.Data());
      }
    }
    if (nzip > 0) { // 압축을 푼 파일들이 있다면
       foo(unzip_dir.Data()); // 임시 디렉토리에 대한 작업 실시
       임시 디렉토리 삭제;
       printf("For check 3: path = %s\n", path); // for check
    }
}

이런 식인데요,

이게 어떤 때는 원하는 대로 잘 됩니다.

근데 어떤 때는 const char*로 정의된 저 path의 내용이 달라져 버리는 군요.
즉 잘 나가다가, 중간 쯤에서, path의 내용이
원래 path명과 파일 명들의 이상하게 조합되어서 적당히 짤린 이름으로 대체되어 버리는 현상이 생깁니다.

특히 임시 디렉토리 생성/처리/삭제 후에,
check 3에서는 정상적으로 보이는 데 그 다음 check 2에서는 이상한 이름으로 바뀌어 있는 경우가
발생합니다.

이 문제로 며칠을 끙끙거리고 있는데 혹시 짐작가시는 데 있으시면 조언 부탁 드립니다.
혹시, 뭔가 말이 안되는 것 같지만, const char* 형식의 인수를 가진 함수는 재귀호출할때
무슨 문제가 있거나 아님 다른 주의점 같은데 있으려나요 ?

dltkddyd의 이미지

값을 넘기는 것이 아니라 주소를 넘기는 것으로 압니다. 함수의 인수로 주소를 넘길 수 있죠. 타입이 차원이 같은 포인터 변수라면 가능합니다.

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

jick의 이미지

올려주신 프로그램은 실제 프로그램과 다르군요. 현재 형태로는 foo(unzip_dir.Data())를 부르기 전에 unzip_dir 변수가 사라져 버리므로 컴파일이 안될 텐데요.

실제로 돌아가고 실제로 문제가 발생하는 소스를 올려주세요. 그래야 뭐가 문제가 있는지 알죠.

parkon의 이미지

말씀하신게 맞습니다. 실제 코드에서는 unzip_dir이 저 루프 외부에 정의되어 있구요.
근데 실제 코드를 다 올리기엔 너무 지저분하고 길어서요...,

이 글 올리고 난 후 다시 몇가지 시도를 해 봤는데
위 프로그램을 돌리는 cint 마크로 파일에서
예를 들어

{
   ...
   const char *base_dir = "../data_base";
   const char *dir_name = "my_data_dir";
   TString path = Form("%s/%s", base_dir, dir_name);
   foo(path.Data());
   ...
}

이렇게 하면 생기던 문제들 중 상당수가
{
   ...
   foo("../data_base/my_data_dir");
   ...
}

이렇게 하면 해결되는데, 감을 잘 못잡겠네요.
위의 foo 함수가 아닌 다른 곳에서 어떤 이상한 일이 일어나고 있다는 반증일까나요 ?
익명 사용자의 이미지

path.Data()가 null termination 이 안되는 것 아닐까요? foo 함수의 인자로 뭐가 들어오는지 한 번 보시죠.

댓글 달기

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