2015-02-23 97 views
0

當我每次運行我的程序:ns-server時,它會告訴我它解密消息失敗,但是當我使用valgrind時,嘗試找出發生此錯誤的原因,它工作正常。每當我使用valgrind進行調試時,它都能正常工作。 Valgrind的結果是:Valgrind顯示調試結果,但結果不正確

valgrind --leak-check=yes ./ns-server 
==44887== Memcheck, a memory error detector 
==44887== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==44887== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info 
==44887== Command: ./ns-server 
==44887== 
first get nextlen 564 
nextlen is 564 
==44887== Thread 2: 
==44887== Invalid read of size 1 
==44887== at 0x6C49: strlen (vg_replace_strmem.c:427) 
==44887== by 0x100134E6F: StringBuffer::setString(char const*) (in ./ns-server) 
==44887== by 0x100159A4F: XString::setFromAnsi(char const*) (in ./ns-server) 
==44887== by 0x100025396: CkRsa::DecryptStringENC(char const*, bool, CkString&) (in ./ns-server) 
==44887== by 0x1000130EA: My_RSA::MyDecryption(char*, CkString&) (RSAsample.cpp:52) 
==44887== by 0x1000021C1: Server::Register(char*, int, char*) (Server.cpp:164) 
==44887== by 0x100001EAB: Server::Evaluate_MSG(void*) (Server.cpp:75) 
==44887== by 0x409898: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib) 
==44887== by 0x409729: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib) 
==44887== by 0x40DFC8: thread_start (in /usr/lib/system/libsystem_pthread.dylib) 
==44887== Address 0x100b3f150 is 0 bytes after a block of size 128 alloc'd 
==44887== at 0x47E1: malloc (vg_replace_malloc.c:300) 
==44887== by 0x1000020F4: Server::Register(char*, int, char*) (Server.cpp:154) 
==44887== by 0x100001EAB: Server::Evaluate_MSG(void*) (Server.cpp:75) 
==44887== by 0x409898: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib) 
==44887== by 0x409729: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib) 
==44887== by 0x40DFC8: thread_start (in /usr/lib/system/libsystem_pthread.dylib) 
==44887== 

這是結果的一部分。 在這樣的結果,它提到:

by 0x100134E6F: StringBuffer::setString(char const*) (in ./ns-server) 
==44887== by 0x100159A4F: XString::setFromAnsi(char const*) (in ./ns-server) 
==44887== by 0x100025396: CkRsa::DecryptStringENC(char const*, bool, CkString&) (in ./ns-server) 

但是這3個功能來自這是我從http://www.chilkatsoft.com/refdoc/vcCkRsaRef.html下載它們的靜態庫這是否意味着錯誤實際上是在這些功能發生?爲什麼當我使用valgrind運行時,我的項目可以輸出正確的結果?當我在沒有任何調試工具的情況下運行它時,它會輸出「解密失敗」。 Valgrind會改變與我的程序相關的內容嗎?

我的代碼如下:

int main(int argc, const char * argv[]) 
{ 
Server myServer(SERVER_PORT);//initialize server's port num,set up socket 

myServer.Start(); 
return 0; 
} 

int Server::Start() 
{ 

send_public_key server_pub_key; 
server_pub_key.heads.random=random()%10; 
server_pub_key.heads.request_type=PUBLICKEY; 
server_pub_key.heads.length=sizeof(send_public_key); 

strcpy(server_pub_key.pubkey,server_rsa.publickey); 

TCPServer.SetupListen(PortListen,Evaluate_MSG,"",0,PUBLICKEY,(char *)&server_pub_key,server_pub_key.heads.length); 
    return 0; 
} 

int TCPConnect::SetupListen(int port, void * trifunc(void *),char * refuseMSG,int refuseLen,int pub,char *msg,int length) 
{ 
if((mi_SocketToListen=socket(AF_INET,SOCK_STREAM,0))==-1) 
{ 
    printf("create socket failed\n"); 
    return errno; 
} 

struct sockaddr_in ts_SocketAddrToListen; 
ts_SocketAddrToListen.sin_addr.s_addr=INADDR_ANY; 
SetupSocketAddrToTarget(NULL, port, ts_SocketAddrToListen,1); 
if(bind(mi_SocketToListen,(struct sockaddr *)&ts_SocketAddrToListen,sizeof(struct sockaddr)) == -1) 
{ 
    printf("establish socket failed!\n"); 
    return errno; 
} 
if(listen(mi_SocketToListen,99)==-1) 
{ 
    printf("listen failed\n"); 
    return errno; 
} 
while (1) 
{ 
    int ti_sockfd; 
    struct sockaddr_in ts_sockaddr; 
    socklen_t ti_size = sizeof(struct sockaddr_in); 
    if((ti_sockfd=accept(mi_SocketToListen,(struct sockaddr *)&ts_sockaddr,&ti_size))==-1) 
    { 
     printf("accept user failed\n"); 
     return errno; 
    } 
    if (threadlist.size() < mi_MaxConnection) 
    { 

     if(pub==80)//if this needs me to send a public key immediately afther i accept it 
     { 

      SendMsg(ti_sockfd, msg,length); 

     } 

     mm_clients.insert(std::pair<int,struct sockaddr_in>(ti_sockfd,ts_sockaddr)); 

     pthread_t tp_threadfd; 

     pthread_create(&tp_threadfd,NULL,trifunc,(void *)&ti_sockfd); 

     threadlist.push_back(tp_threadfd); 

    } 
    else 
    { 
     SendMsg(ti_sockfd, refuseMSG, refuseLen); 
     CloseConnect(ti_sockfd,NULL); 
    } 
} 

return 0; 
}; 

void * Server::Evaluate_MSG(void *arg) 
{ 

int socketfd = *((int *) arg); 

header checkheader; 
int err; 
while (true) 
{ 
    err = 0; 

    char * msg; 
    char *ip; 
    ip=(char *)malloc(sizeof(char)*INET_ADDRSTRLEN); 
    memset(ip,0,sizeof(char)*INET_ADDRSTRLEN); 

    int nextlen=Server::TCPServer.GetNextlen(socketfd); 

    msg=(char *)malloc(sizeof(char)*nextlen); 
    memset(msg,0,sizeof(char)*nextlen); 

    msg=Server::TCPServer.Receive(socketfd, nextlen); 

    //Server::TCPServer.Receive(socketfd,msg); 
    struct sockaddr_in sender_ip; 
    memset(&sender_ip,0,sizeof(struct sockaddr_in)); 

    sender_ip=Server::TCPServer.GetInfoBySocket(socketfd); 

    inet_ntop(AF_INET,&sender_ip.sin_addr,ip,INET_ADDRSTRLEN); 

    memset(&checkheader,0,sizeof(header)); 
    memcpy(&checkheader,msg,sizeof(header)); 
    switch(checkheader.request_type) 
    { 
     case REGISTER: 
      err = Register(msg, socketfd,ip); 

      break; 
     case LOGIN: 
      err=Login(msg, socketfd,ip); 
      break; 
     default: 
      break; 
    } 
    free(ip); 
    free(msg); 
    if (err<0) 
    { 
     cout<<"error!"<<endl; 
     pthread_exit(0); 
    } 
} 

} 

int Server::Register(char *msg,int sockfd,char *ip) 
{ 
request_register reg; 
memset(&reg,0,sizeof(request_register)); 
memcpy(&reg,msg,sizeof(request_register)); 



if(reg.real_pass!=REAL_PASS) 
{ 
    //ignore 
} 
else 
{ 
    send_user_success success_err; 
    success_err.heads.random=random()%10; 
    success_err.heads.length=sizeof(success_err); 
    CkString user_name_outData; 
    char *recv_username; 
    recv_username=(char *)malloc(sizeof(char)*LENGTH_CIPHERTEXT); 
    memset(recv_username,0,sizeof(char)*LENGTH_CIPHERTEXT); 
    memcpy(recv_username,reg.username,sizeof(char)*LENGTH_CIPHERTEXT); 

    server_rsa.MyDecryption(recv_username,user_name_outData); 
    //it decrypt fails 

    cout<<"after returning:"<<user_name_outData.getString()<<endl; 

-------------------以上是註冊()函數部分,實在是太長了,我只是樁部的它----------------

bool My_RSA::MyDecryption(char *ciphertext,CkString &outData) 
{ 
rsaDecryptor.put_EncodingMode("hex"); 
rsaDecryptor.ImportPrivateKey(privatekey); 
bool userPrivateKey; 
userPrivateKey=true; 

const char *cipher; 
cipher=ciphertext; 


const char * decryptedStr ; 
decryptedStr= new char[SAY_MAX]; 
memset((char *)decryptedStr,0,sizeof(char)*SAY_MAX); 

bool test=(char *) rsaDecryptor.DecryptStringENC(ciphertext, userPrivateKey, outData);//(decryptedStr, userPrivateKey); 
if (!test) { 
    cout<<"decrypt failed"<<endl; 
    return false; 
} 

return true; 

} 

的錯誤是:它會顯示「解密失敗」時,我沒有任何調試工具運行,但它會用valgrind完全解密。 這是頭(部分):

static std::map <string,struct user_info> user_info_map;//string is user's name 
static My_RSA server_rsa; 

class Server 
{ 
public: 
Server(int p); 

protected: 

static TCPConnect TCPServer; 

public: 
int PortListen; 


protected: 
static int Register(char *msg,int sockfd,char *ip); 
static int Login(char *msg,int sockfd,char *ip); 
static int Lock_Un_Out(char *msg,int sockfd,int lock_unlock); 

static int Check_User(int sockfd); 
static int Send_User(char *msg,int sockfd); 

static int Update(char *msg,int sockfd); 
public: 
int Start(); 

static void * Evaluate_MSG(void *arg); 
}; 

的錯誤是部分是,它解密失敗,但我不覺得,因爲當我的valgrind或Xcode中運行它,它是關係到DecryptStringENC的功能,經常工作良好。

+0

是的,valgrind通過檢測來改變你的代碼。這可能會改變內存操作的結果。在valgring或任何其他調試工具下運行也會改變可能改變多線程程序行爲的時間。 **你有沒有調查過可能會導致「無效的大小1的讀取」?你想發佈你的代碼嗎?** – dmitri 2015-02-23 07:42:28

+0

我試圖找到原因,它說:無效的讀取大小1 == 44887 ==在0x6C49:strlen(vg_replace_strmem.c:427) == 44887 = = by 0x100134E6F:StringBuffer :: setString(char const *)(in ./ns-server)我看不到StringBuffer :: setString(char const *)的函數裏面有什麼,它不是由我編碼的,我從它下載網站(這句話是否意味着這個錯誤與此功能有關)。我想發佈我的代碼,但它會發布至少200行相關代碼。我會發布它。 – beasone 2015-02-23 08:03:02

回答

2

現在我明白了爲什麼會發生錯誤。當我將密文傳入MyDecryption(char *ciphertext,CkString &outData) 時,我設置它的大小爲128bytes(因爲當我使用strlen查看密文的大小時,它顯示128)。但我突然想到,也許我應該使用大小爲129字節的malloc密文,因爲'/ 0'將被附加到一個字符串。然後,問題解決!!!!!!!

+0

'std :: vector'可能會幫助您解決代碼中的一堆問題。 – 2015-02-23 17:23:34

+0

感謝您的諮詢! – beasone 2015-02-23 18:25:15