Solved

Cannot access cout from inside a dll

Posted on 2004-04-27
12
701 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
12 Comments
 
LVL 6

Expert Comment

by:Mafalda
ID: 10937650
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
ID: 10937808
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
ID: 10941029
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:platinumdragon
ID: 10941044
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
ID: 10941630
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
 

Author Comment

by:platinumdragon
ID: 10941714
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
ID: 10951256
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
ID: 10953076
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
ID: 10953434
Visual C++ Projects >> .NET >> Class Library
0
 

Author Comment

by:platinumdragon
ID: 11069795
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
ID: 11293881
PAQed, with points refunded (250)

Netminder
EE Admin
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
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.

752 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