Click here to Skip to main content
15,893,663 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,
I am quite new to C++ and I my code crashes after exiting the function in this place of "mlock.c" file:
C++
void __cdecl _unlock (
        int locknum
        )
{
        /*
         * leave the critical section.
         */
        LeaveCriticalSection( _locktable[locknum].lock );
}


My function looks like this and should return false:

C++
bool cCardClientNewCamd::SendMessage(const unsigned char *data, int len, bool UseMsgId, const struct CustomData *cd, comm_type_t commType)
{
  ...........
  return true;// cCardClientNewCamd::SendMsg(netbuf,len);
}

bool cCardClientNewCamd::CmdSend( net_msg_type_t cmd, comm_type_t commType)
{
  unsigned char buffer[3];
  buffer[0] = cmd; buffer[1] = buffer[2] = 0;
  return SendMessage(buffer,sizeof(buffer),false,0,commType);
}

int cCardClientNewCamd::CmdReceive( comm_type_t commType)
{
  unsigned char buffer[CWS_NETMSGSIZE];
  if(ReceiveMessage(buffer,false,0,commType)!=3) return -1;
  return buffer[0];
}

bool cCardClientNewCamd::SendMessage(const unsigned char *data, int len, bool UseMsgId, const struct CustomData *cd, comm_type_t commType)
{
  ......
  return true;// cCardClientNewCamd::SendMsg(netbuf,len);
}

int cCardClientNewCamd::ReceiveMessage(unsigned char *data, bool UseMsgId, struct CustomData *cd, comm_type_t commType)
{
  unsigned char netbuf[CWS_NETMSGSIZE];
  .......
  return returnLen;
}


bool cCardClientNewCamd::str2char(unsigned char *data,int *len,bool f, std::string s) 
{
	std::istringstream iss(s);
	unsigned char buf[240];
	int c=0;
	do
    {
		std::string sub;
        iss >> sub;
		int val= 0;
		sscanf(sub.c_str(), "%2x", &val);
		buf[c]=val;
		c++;
		//std::cout << "Substring: " << sub << std::endl;
    } while (iss);

	if (f)
	{
		*len = 2;
		memcpy (data,buf,2);
	}else{
		*len =(int) buf[1];
		memcpy (data,buf+2,*len);
	}
  return true;
}

int cCardClientNewCamd::RecvMsg(unsigned char *data, int id, bool f)
{
	int len=0;

	if (id==0)//SVR: Random data
		str2char(data,&len,f,(f?"0 E":"DE 75 27 A0 72 AB 83 72 F2 7D 34 3C AC 36"));

	return len;
}


// Failing to return function
bool cCardClientNewCamd::Login(void)
{
       unsigned char randData[14];
        int len=cCardClientNewCamd::RecvMsg(randData,0,false); //<-AFTER THIS CALL FAILS TO RETURN
	return false; //<- FAILS AFTER
	//....//
  	if(!SendMessage(buffer,buffer[2]+3,true,&cd) || CmdReceive()!=MSG_CLIENT_2_SERVER_LOGIN_ACK) {

		if(NextProto()) return Login();    
		return false;    
	}
	//...//
	return true;
}


Code calling this:
C++
int _tmain(int argc, _TCHAR* argv[])
{
	cCardClientNewCamd *cc = new cCardClientNewCamd("525");
	if (cc->Login() == true) // <- NEVER COMES OUT HERE
	{
		unsigned char data[240];//CWS_NETMSGSIZE];
		CustomData cd;
	}
	int hr=0;	
	printf("\n");
	system("pause");
	return 0;
}


header descriptions:
C++
class cCardClientNewCamd :  private cTripleDes {
private:
  //cNetSocket so;
  unsigned char configKey[14];
  unsigned short netMsgId;
  int caId, protoVers, cdLen;
  bool emmProcessing;
  char username[USERLEN], password[PASSWDLEN];
  void InitVars(void);
  void InitProtoVers(int vers);
  bool NextProto(void);
  void InitCustomData(struct CustomData *cd, const unsigned short PrgId, const unsigned char *data);
  void PrepareLoginKey(unsigned char *deskey, const unsigned char *rkey, const unsigned char *ckey);

protected:
	int cCardClientNewCamd::RecvMsg(unsigned char *data, int id, bool f);
	bool cCardClientNewCamd::str2char(unsigned char *data,int *len,bool f, std::string s);
	void cCardClientNewCamd::prn(std::string txt, unsigned char *a, int nLen);
public:
  cCardClientNewCamd(const char *Name);
  virtual bool Login(void);
  // Client Helper functions
  bool SendMessage(const unsigned char *data, int len, bool UseMsgId, const struct CustomData *cd=0, comm_type_t commType=COMMTYPE_CLIENT);
  int ReceiveMessage(unsigned char *data, bool UseMsgId, struct CustomData *cd=0, comm_type_t commType=COMMTYPE_CLIENT);
  int cCardClientNewCamd::ReceiveMessage(unsigned char *data, bool UseMsgId, struct CustomData *cd, std::string txt, int id, comm_type_t commType=COMMTYPE_CLIENT);
  bool CmdSend( net_msg_type_t cmd,  comm_type_t commType=COMMTYPE_CLIENT);
  int CmdReceive( comm_type_t commType=COMMTYPE_CLIENT);


Could anyone explain why this does not work?

Note: Narrowed down where causes fault so after return crashes (line "int len=cCardClientNewCamd::RecvMsg(randData,0,false);") but not sure what is the problem. Now after removing thread class code crashes somewhere else: get a message box with "No Source Code Available for the Current Location".
Posted
Updated 5-Jan-12 4:47am
v6
Comments
JackDingler 5-Jan-12 8:41am    
I don't see where you lock and unlock.

Where does the debugger take you when it crashes?
Tomazas77 5-Jan-12 9:47am    
stops inside void __cdecl _unlock() function
Chuck O'Toole 5-Jan-12 10:52am    
Crashing where there is "no source code available" usually means off in some library routine you called with bad arguments. When this happens, use the debuggers "stack" window and walk the call frames backwards until you find yourself back in your code. That should identify where *you* called something that blew up.
Tomazas77 5-Jan-12 12:07pm    
This is what I get in stack:

32800042()
> msvcr90d.dll!_CrtIsValidHeapPointer(const void * pUserData=0x651bd496) Line 2103 C++
0042fd58()
NewCamD_test.exe!pre_cpp_init() Line 327 + 0x21 bytes C
0042fe2c()
kernel32.dll!7556339a()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!76f49ed2()
ntdll.dll!76f49ea5()
Chuck O'Toole 5-Jan-12 12:47pm    
Double-Clicking on each line will take you to the code for that call. Is "NewCamD_test" your program? If so, the call around line 327 (or the line before) in pre_cpp_init() is the call.

PS, blowing up in a routine called "IsValidHeapPointer()" is a clue in itself, you probably exceeded some structure or array bounds.

you need to learn to debug your code with the tools available, single stepping, etc. I am not going to debug this for you one message at a time.

The short answer is: don't use multithreading/multiprocessing, or anything related. The problems invoked by parallelism and synchronization cause splitting headaches even to experts, and there are certain aspects that simply have no clean solutions. And that is the conclusion even the members of the C++ Standards committee themselves came to! (which is the reason why there is so little support for multi-threading in standard C++)

If you really want your problem solved we'll need a lot more information than this, e. g. how you manage your threads and especially what kind of threading library you are using; who locks what and when and why; what the various variables you access in the code above are supposed to hold, etc.. And even that may not be enough.

So far the only useful piece of information I thought I could gather from your code was that you call SendMessage which might have referred to the Windows function by that name. However, SendMessage (the Windows function) expects a window handle as it's first parameter, so either you're calling it wrong, or you may be calling an entirely different function of your own instead, and we have no information whatsoever about what that function does.
 
Share this answer
 
Comments
JackDingler 5-Jan-12 8:58am    
Good point there. SendMessage() isn't very safe as a multithreaded communication mechanism. It's better to put your data in a lockable shareable place and use PostMessage() if you need to use windows messaging to notify the app that data is waiting.
JackDingler 5-Jan-12 9:01am    
And because you say you're new to C++, Stefan_Lang's advice to avoid multithreaded programming is a good plan. You have enough problems to tackle without adding that overhead.
Tomazas77 5-Jan-12 9:44am    
Removing Threading did not solved the issue. Given code I am trying to convert from Linux version to Windows. The original code does use multi-threading but I am currently working on console application and don't need any multi-threading. So for this reason I ignored any multi-threading lines. So purely in my code I am not using any threads.
But I am getting to the point where socket has to be used.
Stefan_Lang 5-Jan-12 10:09am    
Err... if you don't use multithreading, what are SendMessage() and CmdReceive() supposed to do, and when?

Again, if you don't truly, deeply, understand multithreading, don't do it. And "don't do it" does include "don't try to convert one". Note that, since multithreading isn't part of the C++ language, you cannot easily port such programs between platforms! And just throwing away parts of the program will never work!

If you need the functionality of a particular program on one system, chances are that you can find an existing implementation of the same functionality on the other. There's rarely a need to do the conversion yourself.
Tomazas77 5-Jan-12 10:17am    
Sorry for incomplete code, I've added more. SendMessage is a function in class not a threading SendMessage().
I'm posting this in a separate solution because my other solution was posted under the premise that there is no use explaining problems of multithreading to a new C++ programmer.

This is just about your problem with str2char. I've added notes as comments and explained them below:
C++
bool cCardClientNewCamd::str2char(unsigned char *data,int *len,bool f, std::string s) 
{
   std::istringstream iss(s);
   unsigned char buf[240];                  // 1
   int c=0;
   do
   {
      std::string sub;
      iss >> sub;                           // 2
      int val= 0;
      sscanf(sub.c_str(), "%2x", &val);
      buf[c]=val;                           // 3
      c++;                                  // 4
   } while (iss);                           // 5
 
   if (f)
   {
      // ...
   }else{
      *len =(int) buf[1];                   // 6
      memcpy (data,buf+2,*len);             // 7
   }
   return true;
}

1) you declared a buffer without initializing it. This isn't necessarily a problem, but... see below

2) You read the variable sub of type string from a stringstream - which means all of it! Spaces are valid characters and as such part of that string, not a separator as you might have expected.

3) This should work as intended, at least the first time, when you assign buf[0]. I'm not so sure about the next times - if there are any (see below)

4) c will be incremented ... once, for all I can say (see below)

5) I'm not aware there is a conversion function from strstream to bool? Normally you should use operator!() or the member functions good() or bad() or eof() to test the state of the strstream!? Even if your compiler didn't complain, this might be worth fixing. But see below...

In any case, there's two possibilities: either your condition will never be true and your loop will run infinitely, or it terminates immediately at this point (since the entire contents have been read out already), leading to the problems indicated above, and described below.

6) buf[1] has never been initialized, so you're copying an undefined value!

7) buf+2 contains just more uninitialized memory - but it doesn't really matter because you're trying to copy a data block of undetermined length (see 6).


My advice
Forget strstream and string for now and rewrite that function with standard C - just iterate over that string character for character so you know what you're doing. Once it works like it should you can always come back and try your luck with C++ classes, but if you do, try to not mix that with C style functions such as sscanf - that's just asking for trouble.
 
Share this answer
 
Comments
Tomazas77 5-Jan-12 12:30pm    
Thanks for advice, I've been searching on web for a function to convert string hex values separated by space to unsigned chars. I came across only with this solution.

And, I've solved the issue. You pointed out in option 7: the length to copy was much bigger (117 bytes instead 14). This was the fault.
Thanks
Found it at last, the length of string to copy memory in line 7 was incorect (much bigger than supposed to be).

Fixing to this resolved my issue:
C++
bool cCardClientNewCamd::str2char(unsigned char *data,int *len,bool f, std::string s) 
{
	std::istringstream iss(s);
	unsigned char buf[240];
	int c=0;
	do
    {
		std::string sub;
        iss >> sub;
		int val= 0;
		sscanf(sub.c_str(), "%2x", &val);
		buf[c]=val;
		c++;
    } while (iss);

	if (f)
	{
		*len = 2;
		memcpy (data,buf,2);
	}else{
		*len =(int) buf[1];
		memcpy (data,buf+2,(size_t) *len);
	}
  return true;
}

int cCardClientNewCamd::RecvMsg(unsigned char *data, int id, bool f)
{
	int len=0;

	if (id==0)//SVR: Random data
		str2char(data,&len,f,"0 E DE 75 27 A0 72 AB 83 72 F2 7D 34 3C AC 36");
	
	return len;
}


Thanks for support.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900