1

私が取り組んでいるプロジェクトのデバッグ クラスを作成しようとしていますが、デバッグ オブジェクトを渡す必要がないので、このようにしようとしていました。ただし、コンパイラまたはリンカが、作成中の実装をスキップしているように見える理由がわかりません。

#include "Debug.cpp" を main.cpp に追加すると、このコードは問題なく動作します。実装を .h ファイルに入れるか、Debug.cpp を #include しない限り、コンパイラは何らかの理由で open、close、および print 関数の実装を欠いています。

Debug.cpp に実装が表示されない理由がわかりましたか?

関係ないと思いますが、現在、debug.h と debug.cpp は 1 つのプロジェクトにあり、main.cpp は別のプロジェクトにあります (両方とも同じソリューション内ですが、Visual Studio 2008)。main.cpp は実行可能ファイルとしてビルドされ、debug.h と debug.cpp はダイナミック ライブラリ (dll) としてコンパイルされます。

Debug.h

コード: すべて選択

#define BUFFER_SIZE 1028
#include <string>
#include <fstream>
#include <assert.h>
#include <stdarg.h> // va_arg

#ifndef _DEBUG_H_
#define _DEBUG_H_
namespace Debugger
{
   // member variables
   extern const unsigned int m_sizebuffer;
   extern std::ofstream m_file;
   extern bool m_fileopened;
   extern char m_buffer[BUFFER_SIZE];
   extern va_list m_vl;

   /*
      'extern' keyword there to remind myself that
      all functions are implicitly extern, so
      declaring variables with 'extern' is more intuitive.
      Will remove when the 'extern' keyword becomes second nature to me.
   */
   extern void open_file();
   extern void close_file();
   extern void print(const char* fmt, ...);
}

#endif

Debug.cpp

コード: すべて選択

#ifndef _DEBUG_H_
#include "Debug.h"
#endif

namespace Debugger
{
   const unsigned int m_sizebuffer = BUFFER_SIZE;
   std::ofstream m_file;
   bool m_fileopened;
   char m_buffer[BUFFER_SIZE];
   va_list m_vl;

   void Debugger::open_file()
   {
      // file cannot already be opened.
      assert(!m_fileopened);
      m_file.clear(); // clear contents of debug file.

      //if directory already exists nothing *SHOULD* happen. platform dependent.
      system("mkdir Data");

      m_file.open("./Data/ErrorLog.txt");   // hard-coding filename is intentional
      if(m_file.is_open() )
      {
         m_fileopened = true;
         print("Debug: successfully loaded file './Data/ErrorLog.txt' \n" );
      }
   }

   void Debugger::close_file()
   {
      if(m_fileopened)
      {
         m_file.close();
         m_fileopened = false;
      }
   }

   /*
      WARNING: Should only accept c-style strings only. If output is ever cryptic double check
      that we are not passing c++ Strings instead of char*, do not know how to differentiate if
      fmt is a c-style string (char*) or a C++ String.
   */
   void Debugger::print(const char* fmt, ...)
   {
      if(!m_fileopened)
      {
         open_file();
         print("Debug file opened. \n");
      }
      int retval = 0;

      va_start(m_vl, fmt);
      retval = vsnprintf_s(m_buffer, m_sizebuffer, m_sizebuffer, fmt, m_vl);
      va_end(m_vl);
      m_file << m_buffer;
      m_file.flush();

      assert(retval > 0);
   }
}

main.cpp

コード: すべて選択

#include "stdlib.h"
#ifndef _DEBUG_H_
#include "Debug.h"
#endif

int main(int argc, char* argv[])
{
   //Debugger::print("this should work~! yay");

   return EXIT_SUCCESS;
}

メイン関数の印刷行のコメントを外すと、次のエラーが発生します。

コード: すべて選択

1>LINK : C:\Users\Benjamin\Desktop\vs projects (c++)\Game Debugger\debug class\Debug\Smashteroids.exe not found or not built by the last incremental link; performing full link
1>main.obj : error LNK2019: unresolved external symbol "void __cdecl Debugger::print(char const *,...)" (?print@Debugger@@YAXPBDZZ) referenced in function _main
1>C:\Users\Benjamin\Desktop\vs projects (c++)\Game Debugger\debug class\Debug\Smashteroids.exe : fatal error LNK1120: 1 unresolved externals

編集:私の元の議論へのリンク:

http://elysianshadows.com/phpBB3/viewtopic.php?f=6&t=5328&start=999999

4

1 に答える 1

0

関数名にDebug.cpp追加Debugger::の修飾子があると思います。たとえばvoid print(const char* fmt, ...)、代わりに cpp ファイルで試してください。関数はすでにDebugger名前空間に含まれているため、再度修飾する必要はありません。

編集:実際にDebug.o最終的な実行可能ファイルにリンクしましたか? すべてのオブジェクト ファイルをバイナリにリンクしないと、次のようなリンカ エラーが発生します。Java のようなランタイムとは異なり、C++ はprint. それぞれのファイルをすべてリンクして、明示的に伝える必要があります。

于 2010-08-31T02:26:07.447 に答える