с++ некорректное выделение данных из области памяти

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by realcoder, 22 Jul 2011.

  1. realcoder

    realcoder Member

    Joined:
    9 Dec 2010
    Messages:
    226
    Likes Received:
    11
    Reputations:
    4
    такая проблема:
    пишу радмин. испольузю бинарный протокол как у мэйлагента(очень удобно - сначала заголовок, потом данные четырехбайтные целые и строки с префиксной длиной).
    вот при авторизации возникла проблема: строки некорректно читаются(идет префиксная длина-логин-префиксная длина - пароль). с скоета считывается область памяти(void * или на winapi LPVOID)
    из нее через memcpy выделяются данные. так вот логин вообще пустой, а вместо пароля какаято кракозябра. вот код:
    Code:
    			if((pack.command==CS_LOGIN)&&(pack.sing==SIGN))
    			{
    			wprintf(L"Login reques recived.checking autorization data...\n");
    			void *lpData=malloc(1024);
    			ZeroMemory(lpData,1024);
    			if(recv(AcceptSocket,(char *)lpData,pack.datalen,0)>0)
    			{
    				FILE *fFile=fopen("test.bin","w");
    				fwrite(lpData,pack.datalen,1,fFile);
    				fclose(fFile);
    				DWORD dwOffset=0;
    				DWORD dwLoginLen=0;
    				dwOffset+=sizeof(DWORD);
    				memcpy(&dwLoginLen,lpData,dwOffset);
    				char *szLogin=(char *)malloc(256);
    				ZeroMemory(szLogin,256);
    				dwOffset+=dwLoginLen;
    				memcpy(szLogin,lpData,dwOffset);
    				DWORD dwPassLen=0;
    				dwOffset+=sizeof(DWORD);
    				memcpy(&dwPassLen,lpData,dwOffset);
    				char *szPass=(char *)malloc(256);
    				ZeroMemory(szPass,256);
    				dwOffset+=dwPassLen;
    				memcpy(szPass,lpData,dwOffset);
    				strcat(szLogin,"\0");
    				strcat(szPass,"\0");
    				printf("loginLen: %d; Login %s; PassLen: %d; Pass: %s; recived: %d; readed: %d",dwLoginLen,szLogin,dwPassLen,szPass,pack.datalen,dwOffset);
    				if(validAuth(szLogin,szPass))
    				{
    				pack.command=SC_LOGIN_OK;
    				pack.datalen=0;
    				send(AcceptSocket,(char *)&pack,sizeof(pack),0);
    				wprintf(L"login ok. login_ok pack sended...");
    				}
    else
    				{
    				pack.command=SC_LOGIN_FAIL;
    				pack.datalen=0;
    				send(AcceptSocket,(char *)&pack,sizeof(pack),0);
    				wprintf(L"login fail!. login_fail pack sended...");
    				}
    				
    			}
    			
    			}
    	
    
    вот содержимое файла test.bin(в него записывается то сто приходит на сокет после заголовка). все корректно и правильно прислано:
    [​IMG]
    вот как видно переменные под отладчиком встроенным в visual studio:
    [​IMG]
    szLogin И szPass имеют некорректные значения. как решить подобную проблему?
     
    #1 realcoder, 22 Jul 2011
    Last edited: 22 Jul 2011
  2. alexey-m

    alexey-m Elder - Старейшина

    Joined:
    15 Jul 2009
    Messages:
    518
    Likes Received:
    100
    Reputations:
    37
    ну а указатель в lpData кто будет перемещать, и уж если у тебя есть длина строки, то и выделяй под нее сколь нужно памяти, а не "гадай" фиксированными значениями
    а у тебя сейчас так выходит:
    Code:
    	dwOffset+=sizeof(DWORD);
    
    	// скопировал в dwLoginLen 4 первых байта из lpData
    	memcpy(&dwLoginLen,lpData,dwOffset);
    	
    	char *szLogin=(char *)malloc(256);
    	
    	ZeroMemory(szLogin,256);
    	
    	// dwOffset присваиваешь сколь надо скопировать байт
    	dwOffset+=dwLoginLen;
    	
    	// скопировал в szLogin первых dwOffset байт из lpData
    	memcpy(szLogin,lpData,dwOffset);
    
     
    #2 alexey-m, 22 Jul 2011
    Last edited: 22 Jul 2011
  3. realcoder

    realcoder Member

    Joined:
    9 Dec 2010
    Messages:
    226
    Likes Received:
    11
    Reputations:
    4
    спасибо.понял свою ошибку.переделал вот так:
    Code:
    	if((pack.command==CS_LOGIN)&&(pack.sing==SIGN))
    			{
    			wprintf(L"Login reques recived.checking autorization data...\n");
    			void *lpData=malloc(1024);
    			ZeroMemory(lpData,1024);
    			if(recv(AcceptSocket,(char *)lpData,pack.datalen,0)>0)
    			{
    				FILE *fFile=fopen("test.bin","w");
    				fwrite(lpData,pack.datalen,1,fFile);
    				fclose(fFile);
    				DWORD dwOffset=0;
    				DWORD dwLoginLen=0;
    				memcpy(&dwLoginLen,(void *)((DWORD)lpData+dwOffset),sizeof(DWORD));
    				dwOffset+=sizeof(DWORD);
    				char *szLogin=(char *)malloc(dwLoginLen);
    				ZeroMemory(szLogin,dwLoginLen);
    				memcpy(szLogin,(void *)((DWORD)lpData+dwOffset),dwLoginLen);
    				dwOffset+=dwLoginLen;
    				DWORD dwPassLen=0;
    				memcpy(&dwPassLen,(void *)((DWORD)lpData+dwOffset),sizeof(DWORD));
    				dwOffset+=sizeof(DWORD);
    				char *szPass=(char *)malloc(dwPassLen);
    				ZeroMemory(szPass,dwPassLen);
    				memcpy(szPass,(void *)((DWORD)lpData+dwOffset),dwPassLen);
    				dwOffset+=dwPassLen;
    				printf("loginLen: %d; Login %s; PassLen: %d; Pass: %s; recived: %d; readed: %d",dwLoginLen,szLogin,dwPassLen,szPass,pack.datalen,dwOffset);
    				if(validAuth(szLogin,szPass))
    				{
    				pack.command=SC_LOGIN_OK;
    				pack.datalen=0;
    				send(AcceptSocket,(char *)&pack,sizeof(pack),0);
    				wprintf(L"login ok. login_ok pack sended...");
    				}
    				else
    				{
    				pack.command=SC_LOGIN_FAIL;
    				pack.datalen=0;
    				send(AcceptSocket,(char *)&pack,sizeof(pack),0);
    				wprintf(L"login fail!. login_fail pack sended...");
    				}
    				
    			}
    			
    			}
    
    только теперь в конце строк кроме того что нужно появляется еще какаято херня:
    [​IMG]
    как сделать чтобы в строке было только то сто нужно без этих кракозябр на конце?
     
  4. alexey-m

    alexey-m Elder - Старейшина

    Joined:
    15 Jul 2009
    Messages:
    518
    Likes Received:
    100
    Reputations:
    37
    выделяй память на 1 символ больше и ставь ноль в конце, и вообще сделай что-то типа класса или макросов, которые тебе будут возвращать элементарный данные в виде int DWORD, BYTE, char *, в дальнейшем это тебе очень упростит разбор ответов
     
  5. realcoder

    realcoder Member

    Joined:
    9 Dec 2010
    Messages:
    226
    Likes Received:
    11
    Reputations:
    4
    спасибо за советы!