I have an application that worked fine in Tcl-8.3.x (specifically, 8.3.5), but it crashes in Tcl-8.4.x (I've specifically tried 8.4.2 and 8.4.3).  The code is below; the line that crashes is the one that says "if(Tcl_Init(interp) == TCL_ERROR) {"
 
If I look at the call stack, the bug happens way down in Tcl code somewhere (it's all in assembly, so I can't be more specific).  At the very end of the call stack, it appears that something is trying to access the "00000000" address.
 
I am building this application with VC++6.0; I've tried it on both Win2000 Pro and WinXP Pro.
 
Thanks for any help,
Bob
 
Here's the file which contains the problem (note this will not compile as is; I can supply additional files to interested parties):
 
 
#include "sgio_socket.h"
#include "command.h"
#include "agent_commands.h"
#include "tcl_commands.h"
#include "null.h"
#include "sio_soar_proxy.h"
#include "sio_agent_proxy.h"
#include "tuple_converter.h"
#include "sgio_messages.h"
#include "tsi.h"
#include <tcl.h>
#include <tk.h>
#include <cstdio>
#include <iostream>
#include <strstream>
#include <string>
#include <stdio.h>
 
using namespace std;
 
TSI g_tsi("soarside.log");
SIOSoarProxy* g_soarProxy = null;
std::string* initFile;
int TclLoop(/*Tcl_Interp* interp*/);
 
const char* usage = "soarside.exe <port> <init file>";
const char* defaultInitFile = "soarside-init.tcl";
 
int
main(int argc,char* argv[]) {
     int port = 6969;
     initFile = new std::string(defaultInitFile);
 
     if(argc == 1) {
          // Everything is ok
     }
     else if(argc == 2 || argc == 3 ) {
          std::istrstream argvStream(argv[1]);
          argvStream >> port;
          if(!argvStream) {
               std::cerr << "Could not read port number!\n";
               std::cerr << usage << "\n";
               return -1;
          }
 
          if(argc == 3) {
     initFile->erase(initFile->begin(),initFile->end());
     initFile->append(argv[2]);
    }
     }
     else {
          std::cerr << "Too many parameters!\n";
          std::cerr << usage << "\n";
          return -1;
     }
 
     std::string tmp = "";
     tmp.append(initFile->c_str());
 
     FILE *stream;
 
     //check if specified path is valid by trying to open file
     if( (stream  = fopen( tmp.c_str(), "r" )) == NULL ) {
   std::cerr << "Could not find " << initFile->c_str() << "!\n";
   std::cerr << usage << "\n";
          std::string dummy;
          std::cin >> dummy;
       return -1;
  }
  else
  {
   fclose(stream);
  }
 
     sgio::Socket* client = new sgio::Socket();
 
     try {
          cout << "Awaiting Connection on port " << port << endl;
          sgio::ServerSocket serverSocket(port);
          serverSocket.Accept(client);
     }
     catch(sgio::SocketException& se) {
          cerr << se.what() << "\n";
          return -1;
     }
 
     cout << "Connect accepted" << endl;
     g_soarProxy = new SIOSoarProxy(std::auto_ptr<sgio::Socket>(client));
 
     //Tcl_Main(argc,argv,TclLoop);
 
     int ret = TclLoop(/*interp*/);
     std::cerr << "\nReturned from TclLoop";
     std::cerr << "\ndeleting initFile";
  delete initFile;
 
     std::cerr << "\ndeleting g_soarProxy";
     // the g_soarProxy destructor gets stuck if TclLoop returns with an error
     // fixing this is somewhat messy, so instead we'll just not delete the proxy
     //   and potentially lose some memory.  To minimize this loss, we call the CleanUp
     //   method which cleans up the "safe" stuff (i.e. the non- auto_ptr stuff)
     if(ret==0) {
        delete g_soarProxy;
     } else {
         g_soarProxy->CleanUp();
     }
    
     std::cerr << "\nreturning...";
     return 0;
}
 
int
ProcessInputLinkCmd(ClientData clientData,Tcl_Interp* interp,int argc,Tcl_Obj *const objv[]/*char* argv[]*/) throw() {
 if(argc != 2) {
  interp->result = "Usage: processInputLink <agentName>";
  return TCL_ERROR;
 }
 
    g_soarProxy->RunAgentCommand(Tcl_GetStringFromObj(objv[1],&(objv[1]->length))/*objv[1]->bytes*//*argv[1]*/,DoWMEChangesCommand(interp));
 return TCL_OK;
}
 
int
ProcessOutputLinkCmd(ClientData clientData,Tcl_Interp* interp,int argc,Tcl_Obj *const objv[]/*const char* argv[]*/) throw() {
 if(argc != 3) {
  interp->result = "Usage: processOutputLink <agentName> <listName>";
  return TCL_ERROR;
 }
 int numElements;
     char** elements;
     int result = Tcl_SplitList(interp,/*argv[2]*//*objv[2]->bytes*/Tcl_GetStringFromObj(objv[2],&(objv[2]->length)),&numElements,(const char***)&elements);
     if(result == TCL_OK) {
          TupleConverter tc;
          for(int i = 0; i < numElements; ++i) {
               int check;
               char** tuple;
               result = Tcl_SplitList(interp,elements[i],&check,(const char***)&tuple);
               if(result == TCL_OK && check == 3) {
                    tc.AddTuple(tuple[0],tuple[1],tuple[2]);
        Tcl_Free(reinterpret_cast<char*>(tuple));
               }
               else if(result == TCL_OK) {
                    Tcl_Free(reinterpret_cast<char*>(tuple));
               }
          }
          Tcl_Free(reinterpret_cast<char*>(elements));
          g_soarProxy->RunAgentCommand(/*argv[1]*//*objv[1]->bytes*/Tcl_GetStringFromObj(objv[1],&(objv[1]->length)),
               ReportCommands(tc.GetCommands()));
          return TCL_OK;
      }
      else {
         return TCL_ERROR;
     }
}
 
int
ManageInputLinkCmd(ClientData clientData,Tcl_Interp* interp,int argc,Tcl_Obj *const objv[] /*char* argv[]*/) throw() {
   if(argc == 3) {
    char cmdbuf[256];
    sprintf(cmdbuf,"processInputLink %s\n",Tcl_GetStringFromObj(objv[1],&(objv[1]->length))/*objv[1]->bytes*//*argv[1]*/);
    Tcl_Eval(interp,cmdbuf);
      return TCL_OK;
   }
   else {
      interp->result = "Wrong Number of arguments";
      return TCL_ERROR;
   }
}
 
int
ManageOutputLinkCmd(ClientData clientData,Tcl_Interp* interp,int argc,Tcl_Obj *const objv[] /*char* argv[]*/) throw() {
   if(argc == 4) {
      std::ostrstream out;
      out << "processOutputLink " << Tcl_GetStringFromObj(objv[1],&(objv[1]->length))/*objv[1]->bytes*//*argv[1]*/ << " { " <<
              /*argv[3]*/Tcl_GetStringFromObj(objv[3],&(objv[3]->length))/*objv[3]->bytes*/ << " }\n " << std::ends;
      Tcl_Eval(interp,out.str());
   out.freeze(0);
      return TCL_OK;
   }
   else {
      interp->result = "Wrong Number of arguments";
      return TCL_ERROR;
   }
}
 

//
// TclLoop
// returns: 0 if exits normally, non-zero if exits with error
//
int
TclLoop(/*Tcl_Interp* interp*/) {
 
    std::cerr << "\nEntered TclLoop";
 
    std::string dummy;
 
    std::cerr << "\nTcl_CreateInterp";
    Tcl_Interp* interp = Tcl_CreateInterp();
    std::cerr << "\nTcl_CreateInterp done";
 
    /*std::cerr << "\nTcl_InitStubs";
    dummy = Tcl_InitStubs(interp,"8.3",0);
    if(dummy.c_str()=="") {
        std::cerr << "\nTcl_InitStubs failed";
    } else {
        std::cerr << "\nUsing Tcl version " << dummy.c_str();
    }
 
    std::cerr << "\nTcl_InitStubs done";
 
    std::cerr << "\nTk_InitStubs";
    dummy = Tk_InitStubs(interp,"8.3",0);
    if(dummy.c_str()=="") {
        std::cerr << "\nTk_InitStubs failed";
    } else {
        std::cerr << "\nUsing Tk version " << dummy.c_str();
    }
    std::cerr << "\nTk_InitStubs done";
*/
 
    std::cerr << "\nTcl_Init";
    if(Tcl_Init(interp) == TCL_ERROR) {
        std::cerr << "\n" << interp->result;
        std::cerr << "\nTcl_DeleteInterp";
     Tcl_DeleteInterp(interp);
        std::cerr << "\nTcl_DeleteInterp done";
        return 1;
    }
 
    std::cerr << "\nTcl_Init done";
 
    if(Tk_Init(interp) == TCL_ERROR) {
        std::cerr << "\nTcl_DeleteInterp";
  Tcl_DeleteInterp(interp);
        return 1;
    }
 
    std::cerr << "\nTk_Init done";
 
    char setargc[] = "set argc 0";
    char setargv[] = "set argv {}";
 
    std::cerr << "\nTcl_Eval(interp,setargc)";
    Tcl_Eval(interp,setargc);
    std::cerr << "\nTcl_Eval(interp,setargv)";
    Tcl_Eval(interp,setargv);
    std::cerr << "\nTcl_CreateCommand(interp,managelinks)";
    Tcl_CreateObjCommand(interp,"manageInputLink",ManageInputLinkCmd,null,null);
    Tcl_CreateObjCommand(interp,"manageOutputLink",ManageOutputLinkCmd,null,null);
 Tcl_CreateObjCommand(interp,"processInputLink",ProcessInputLinkCmd,null,null);
 Tcl_CreateObjCommand(interp,"processOutputLink",ProcessOutputLinkCmd,null,null);
 
    std::cerr << "\nTcl_CreateCommand(interp,managelinks) done";
 
    std::string path;
    std::string filename;
 
    // get the directory part of the file
    std::string tmp = "file dirname ";
 tmp.append(initFile->c_str());
 
    std::cerr << "\ngetting file directory";
 
    if(Tcl_Eval(interp,(char*)(tmp.c_str())) == TCL_ERROR) {
  std::cout << interp->result << std::endl;
        Tcl_DeleteInterp(interp);
  return 1;
    } else {
        path = interp->result;
    }
 
    // get the name part of the file
    tmp = "file tail ";
 tmp.append(initFile->c_str());
 
    std::cerr << "\ngetting file name";
    if(Tcl_Eval(interp,(char*)(tmp.c_str())) == TCL_ERROR) {
  std::cout << interp->result << std::endl;
        Tcl_DeleteInterp(interp);
  return 1;
    } else {
        filename = interp->result;
    }
 
    // switch to the directory
    tmp = "cd ";
    tmp.append(path.c_str());
    std::cerr << "\nswitching to directory";
 if(Tcl_Eval(interp,(char*)(tmp.c_str())) == TCL_ERROR) {
  std::cout << interp->result << std::endl;
        Tcl_DeleteInterp(interp);
  return 1;
 }
 
    // source the init file
    tmp = "source ";
    tmp.append(filename.c_str());
    std::cerr << "\nsourcing the init file";
 if(Tcl_Eval(interp,(char*)(tmp.c_str())) == TCL_ERROR) {
  std::cout << interp->result << std::endl;
        Tcl_DeleteInterp(interp);
  return 1;
 }
 
    std::cerr << "\nentering loop";
    while(!g_soarProxy->GetQuit()) {
        while(g_soarProxy->IsATclCommandPending()) {
            std::auto_ptr<TclCommand> tclCommand = g_soarProxy->GetTclCommand();
            tclCommand->Execute(interp);
        }
        Tcl_DoOneEvent(TCL_DONT_WAIT);
    }
 
    return 0;
}