Solved

Cannot access cout from inside a dll

Posted on 2004-04-27
12
667 Views
Last Modified: 2013-12-14
Greetings,

Hopefully, this is an easy question.  Is there a particular reason I cannot access cout from within a dll?  I get the following error whenever I even try to reference it:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at std.operator<<<struct std::char_traits<char> >(basic_ostream<char,std::char_traits<char> >* _Ostr, SByte* _Val) in
 c:\program files\microsoft visual studio .net 2003\vc7\include\ostream:line 706
   at TestDll.sayHello(TestDll* ) in c:\test\testdll\testdll.cpp:line 11
   at TestDll.sayHello(TestDll* )
   at main() in c:\test\testexe\testexe.cpp:line 13

I will post the source code used if requested, but TestExe is simply instantiating the TestDll class from within the dll, and calling its sayHello() member that contains:

[code]std::cout << "Hello" << std::endl;[/code]

Thanks,
Mike

0
Comment
Question by:platinumdragon
  • 6
  • 4
12 Comments
 
LVL 6

Expert Comment

by:Mafalda
Comment Utility
1. Does it work on an executable ?
2. Maybe the problem is the mixing of Managed C++ and non Managed C++ code.
0
 
LVL 6

Expert Comment

by:Mafalda
Comment Utility
The problem seems to be in the environment/project and not the code

I presume that you included

#include <iostream>

System.NullReferenceException points to the Managed C++ objects.

Try to create a new project and choose carefully it's settings
0
 

Author Comment

by:platinumdragon
Comment Utility
Greetings,

Yes, I am including <iostream>.

With new projects, removing the "use managed extensions" setting, and all related code, I still get an error at the same point the NullReferenceException was occurring:

Unhandled exception at 0x10001a00 (TestDll.dll) in : 0xC0000005: Access violation reading location 0x00000004.

The debugger points to the ostream file in the following function (apparently the _Ostr reference is invalid, it fails when assigning a streamsize to _Pad):

template<class _Traits> inline
      basic_ostream<char, _Traits>& __cdecl operator<<(
            basic_ostream<char, _Traits>& _Ostr,
            const char *_Val)
      {      // insert NTBS into char stream
      typedef char _Elem;
      typedef basic_ostream<_Elem, _Traits> _Myos;
      ios_base::iostate _State = ios_base::goodbit;
      streamsize _Count = (streamsize)_Traits::length(_Val);      // may overflow
      streamsize _Pad = _Ostr.width() <= 0 || _Ostr.width() <= _Count
            ? 0 : _Ostr.width() - _Count;
      const typename _Myos::sentry _Ok(_Ostr);

      if (!_Ok)
            _State |= ios_base::badbit;
      else
            {      // state okay, insert
            _TRY_IO_BEGIN
            if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left)
                  for (; 0 < _Pad; --_Pad)      // pad on left
                        if (_Traits::eq_int_type(_Traits::eof(),
                              _Ostr.rdbuf()->sputc(_Ostr.fill())))
                              {      // insertion failed, quit
                              _State |= ios_base::badbit;
                              break;
                              }

            if (_State == ios_base::goodbit
                  && _Ostr.rdbuf()->sputn(_Val, _Count) != _Count)
                  _State |= ios_base::badbit;

            if (_State == ios_base::goodbit)
                  for (; 0 < _Pad; --_Pad)      // pad on right
                        if (_Traits::eq_int_type(_Traits::eof(),
                              _Ostr.rdbuf()->sputc(_Ostr.fill())))
                              {      // insertion failed, quit
                              _State |= ios_base::badbit;
                              break;
                              }
            _Ostr.width(0);
            _CATCH_IO_(_Ostr)
            }

      _Ostr.setstate(_State);
      return (_Ostr);
      }

I am thinking that maybe this has to do with the different memory spaces for the exe and dll?  Perhaps the dll can't access the basic_ostream referenced because it's in a different memory space?  If so, how can I set it locally, or even if I can is it a good idea?

If I could attach a file, I would attach the zipped solution.  It's only 11k.  If you would be willing to email me at pooky_bunny at hotmail.com, I would send it to you.

Thanks,
Mike

0
 

Author Comment

by:platinumdragon
Comment Utility
Oh, and yes, it works when printing to cout before accessing the dll.  It's just the call from within the dll.
0
 
LVL 6

Expert Comment

by:Mafalda
Comment Utility
You can try to copy _Ostr (pass it by value) instead of passing it by reference.
The reference might point to a different memory space, I am not sure.
I still do not exactly get the structure of your program.
Can you describe it ?

is it like this?

main
call cout -> works
call dll
call cout from dll -> fails

????

It will better posted here so other experts can also look at it.

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:platinumdragon
Comment Utility
That won't help if it's an environment/project setting as proposed above, but I'll try anything..

The main in the exe is:

int _tmain()
{
      std::cout << "Test text" << std::endl;

      TestDll* dll = new TestDll();
      dll->sayHello();

      return 0;
}

The sole function of the dll is:

void TestDll::sayHello()
{
      std::cout << "Hello" << std::endl;
}

The output is:
Test text

..and then the exception occurs..

I'm not sure how I would copy cout.  I must admit though I understand the concepts of streams, the technical implementations of them in STL is still a bit hazy for me..

Thanks,
Mike
0
 

Author Comment

by:platinumdragon
Comment Utility
Hmm

It's odd.  Even constructing an ostringstream in the dll fails.  The simple line:

ostringstream fmt;

produces:

Unhandled exception at 0x77f69ecd in ConsoleRunner.exe: 0xC0000005: Access violation writing location 0x00000010.

- Mike
0
 
LVL 6

Expert Comment

by:Mafalda
Comment Utility
How are you creating your dll ?
using a Win32 console project and then selecting it to be a DLL ?
Or creating a MFC DLL ?
I would like to have the same environment to test it out
0
 

Author Comment

by:platinumdragon
Comment Utility
Visual C++ Projects >> .NET >> Class Library
0
 

Author Comment

by:platinumdragon
Comment Utility
Hmm..

I seem to have solved it myself, but I'm not really sure how.  I reconstructed the executable as a Win32 command line executable instead of a .NET command line executable (for a completely unrelated reason).  Now suddenly I can access cout successfully from any of the DLLs.

Thanks,
Mike
0
 
LVL 5

Accepted Solution

by:
Netminder earned 0 total points
Comment Utility
PAQed, with points refunded (250)

Netminder
EE Admin
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
C#  WebForms or MVC 4 89
is twain_32.dll cmpatible with windows 10 ? 10 95
computer science syllabus 3 52
Unable to start eclipse ? 17 82
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now