2012-01-04 103 views
1

我主要有如下代碼:堆棧溢出使用消息隊列

#include "ComHandler.h" 
#include "socketMessage.h" 

#define THIS_IP      "localhost" 
#define C_PORT      32456 
#define S_PORT      25465 
#define S_PORT_UDP     22548 

int main(int argc, char* argv[]) { 

conOptions opts; 
strncpy(opts.password, "PASS", sizeof("PASS")); 
opts.retryQty = 5; 
opts.timeout = 300; 

char dir[INET6_ADDRSTRLEN]; 
strncpy(dir, THIS_IP, sizeof(THIS_IP)); 

if (argv[1][0] == 'C') { 

    opts.connType = CLIENT_HANDLER; 
    opts.thisID = 2; 

    ComHandler comH(opts); 

    char buffer[10]; 
    strncpy(buffer, "Testing", 10); 

    int rtnValue = comH.sendMsg(buffer, 10, 1, TCP_C); 

    std::cout << "Returned Value: " << rtnValue << std::endl; 

} else { 
    opts.connType = SERVER_HANDLER; 
    opts.thisID = 1; 

    ComHandler comH(opts); 
    comH.addConnectionData(2, dir, C_PORT); 
    comH.addConnectionData(comH.getID(), dir, S_PORT); 

    char rcvdTxt[MINIDATA_DATA_SIZE]; 
    comH.receiveMsg(rcvdTxt, MINIDATA_DATA_SIZE, 2, TCP_C); 

    std::cout << "Received: " << rcvdTxt << std::endl; 

    comH.closeCommunications(); 

} 
} 

的代碼是用於測試我的溝通平臺。該平臺運行良好,但處理器(ComHandler)收到消息時會出現問題。當我從ComHandler中調用方法「receiveMsg」時,我在方法的「返回」中得到了一個「檢測到堆棧」。

這是 「ComHandler」 級:

#ifndef COMHANDLER_H_ 
#define COMHANDLER_H_ 

#include "Constants.h" 
#include "ComConstants.h" 
#include "DataLogger.h" 

#include <list> 
#include <math.h> 


#define CLIENT_HANDLER     1 
#define SERVER_HANDLER     2 
#define COMMENT_LINE     '#' 
#define TXT_SEPARATOR      ';' 


#define MINIDATA_DATA_SIZE  (COMDATA_MAX_SIZE - 4* sizeof(int)) 

enum CON_TYPE { 
TCP_C, UDP_C 
}; 


#pragma pack(push) 
#pragma pack(1) 
typedef struct { 
int totalPackets; 
int sequenceNumber; 
int sequenceID; 
int dataSize; 
char data[MINIDATA_DATA_SIZE]; 
} miniData; 
#pragma pack(pop) 

typedef struct connectionOptions { 
unsigned int timeout; 
unsigned int retryQty; 
id_t thisID; 
char password[PASSWORD_MAX_SIZE]; 
int connType; 

connectionOptions() : 
     timeout(CON_TIMEOUT), retryQty(SOCKET_RETRIES), connType(
       SERVER_HANDLER) { 
    memset(password, 0, PASSWORD_MAX_SIZE); 
} 
connectionOptions(connectionOptions& opt) { 
    timeout = opt.timeout; 
    retryQty = opt.retryQty; 
    thisID = opt.thisID; 
    connType = opt.connType; 
    memcpy(password, opt.password, PASSWORD_MAX_SIZE); 
} 

} conOptions; 

class ComHandler { 
private: 
int dataForwarder_ReceiverMsgQueue; 
int dataForwarder_SenderMsgQueue; 

conOptions opts; 

int sequenceID; 

Semaphore ch_mux; 
SharedMemory<comHandlerGlOp> ch_shm; 

void cpyMiniData(miniData* to, miniData* from); 
void createIPCs(); 

public: 
ComHandler(); 
ComHandler(conOptions options); 
ComHandler(id_t thisID); 
virtual ~ComHandler(); 

int receiveMsg(char* buffer, int bufferSize, id_t originID, 
     CON_TYPE type = TCP_C); 
int sendMsg(char* buffer, std::size_t bufferSize, id_t destinationID, 
     CON_TYPE type = TCP_C); 

void configListenersData(char addr[INET6_ADDRSTRLEN], int port, 
     CON_TYPE type); 

void addConnectionData(id_t id, char addr[INET6_ADDRSTRLEN], int port); 
void addConnectionData(const char* file); 
void modifyConnectionData(id_t id, char addr[INET6_ADDRSTRLEN], int port); 
void removeConnectionData(id_t id); 

int getID(); 

void closeCommunications(); 

}; 

#endif /* COMHANDLER_H_ */ 

的comData結構:

typedef struct { 
long type; 
int requestType; 
char destination[INET6_ADDRSTRLEN]; 
char origin[INET6_ADDRSTRLEN]; 
id_t originID; 
id_t destinationID; 
int port; 
pid_t senderPid; 
pid_t originPid; 
char data[COMDATA_MAX_SIZE]; 
} comData; 

而有問題的方法:

int ComHandler::receiveMsg(char* buffer, int bufferSize, id_t originID, 
    CON_TYPE type) { 
comData aux; 

aux.type = DATA_RECEIVE; 
int qtyReceived = 0; 

if (originID != ANY_MSG_ORIGIN) { 
    if (type == TCP_C) 
     aux.requestType = RECEIVE_DATA_FROM_DESTINATION_TCP; 
    else 
     aux.requestType = RECEIVE_DATA_FROM_DESTINATION_UDP; 
} else { 
    if (type == TCP_C) 
     aux.requestType = RECEIVE_ANY_DATA_TCP; 
    else 
     aux.requestType = RECEIVE_ANY_DATA_UDP; 
} 

aux.originID = originID; 
aux.senderPid = getpid(); 
aux.originPid = getpid(); 

msgsnd(dataForwarder_ReceiverMsgQueue, &aux, sizeof(comData), 0); 
msgrcv(dataForwarder_ReceiverMsgQueue, &aux, sizeof(comData), getpid(), 0); 

/* More Code */ 

return qtyReceived; 

} 
後出現

的堆棧溢出錯誤「return qtyReceived;」叫做。而中間的/ * More Code * /是非重要的代碼,因爲如果刪除了那部分,就會出現堆棧粉碎劇照。 多的調試後,我發現,粉碎出現,如果我打電話:

`msgrcv(dataForwarder_ReceiverMsgQueue, &aux, sizeof(comData), getpid(), 0);` 

如果我評論說行,我沒有得到錯誤。 另外,通過調試器,我能夠看到來自隊列的消息以良好的格式和大小到達,完全按照他們的要求。

控制檯輸出爲:

*** stack smashing detected ***: /media/blackhole/workspace/Final/bin/ComTest terminated 
======= Backtrace: ========= 
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7df88d5] 
/lib/i386-linux-gnu/libc.so.6(+0xe7887)[0xb7df8887] 
/media/blackhole/workspace/Final/bin/ComTest[0x804dc6b] 
/media/blackhole/workspace/Final/bin/ComTest[0x804a002] 
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb7d2a113] 
/media/blackhole/workspace/Final/bin/ComTest[0x8049d11] 
======= Memory map: ======== 
08048000-08054000 r-xp 00000000 08:05 256373  /media/blackhole/workspace/Final/bin/ComTest 
08054000-08055000 r--p 0000b000 08:05 256373  /media/blackhole/workspace/Final/bin/ComTest 
08055000-08056000 rw-p 0000c000 08:05 256373  /media/blackhole/workspace/Final/bin/ComTest 
08056000-08077000 rw-p 00000000 00:00 0   [heap] 
b7d0f000-b7d11000 rw-p 00000000 00:00 0 
b7d11000-b7e87000 r-xp 00000000 08:06 525221  /lib/i386-linux-gnu/libc-2.13.so 
b7e87000-b7e89000 r--p 00176000 08:06 525221  /lib/i386-linux-gnu/libc-2.13.so 
b7e89000-b7e8a000 rw-p 00178000 08:06 525221  /lib/i386-linux-gnu/libc-2.13.so 
b7e8a000-b7e8d000 rw-p 00000000 00:00 0 
b7e8d000-b7ea9000 r-xp 00000000 08:06 525242  /lib/i386-linux-gnu/libgcc_s.so.1 
b7ea9000-b7eaa000 r--p 0001b000 08:06 525242  /lib/i386-linux-gnu/libgcc_s.so.1 
b7eaa000-b7eab000 rw-p 0001c000 08:06 525242  /lib/i386-linux-gnu/libgcc_s.so.1 
b7eab000-b7eac000 rw-p 00000000 00:00 0 
b7eac000-b7ed4000 r-xp 00000000 08:06 525251  /lib/i386-linux-gnu/libm-2.13.so 
b7ed4000-b7ed5000 r--p 00028000 08:06 525251  /lib/i386-linux-gnu/libm-2.13.so 
b7ed5000-b7ed6000 rw-p 00029000 08:06 525251  /lib/i386-linux-gnu/libm-2.13.so 
b7ed6000-b7fb4000 r-xp 00000000 08:06 5514  /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16 
b7fb4000-b7fb5000 ---p 000de000 08:06 5514  /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16 
b7fb5000-b7fb9000 r--p 000de000 08:06 5514  /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16 
b7fb9000-b7fba000 rw-p 000e2000 08:06 5514  /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16 
b7fba000-b7fc1000 rw-p 00000000 00:00 0 
b7fdc000-b7fdd000 rw-s 00000000 00:04 163119127 /SYSV02056f32 (deleted) 
b7fdd000-b7fdf000 rw-p 00000000 00:00 0 
b7fdf000-b7fe0000 r-xp 00000000 00:00 0   [vdso] 
b7fe0000-b7ffe000 r-xp 00000000 08:06 525208  /lib/i386-linux-gnu/ld-2.13.so 
b7ffe000-b7fff000 r--p 0001d000 08:06 525208  /lib/i386-linux-gnu/ld-2.13.so 
b7fff000-b8000000 rw-p 0001e000 08:06 525208  /lib/i386-linux-gnu/ld-2.13.so 
bffdf000-c0000000 rw-p 00000000 00:00 0   [stack] 

因此,任何想法?如果您需要關於代碼的一些信息,請問我。

+0

作爲一個猜測,你寫的東西太多,你的'comData' var,它被分配在堆棧上。例如它是50個字節,而你正在寫51個。第51個字節是什麼粉碎堆棧。 – 2012-01-04 18:51:24

+1

您將錯誤的大小傳遞給msgrcv(),它應該是sizeof(comData) - sizeof(long)。好的api設計:( – 2012-01-04 18:58:04

回答

3

根據this,的msgrcv()msgsz參數應該是mymsg結構的mtext構件的尺寸:

struct mymsg { 
    long int mtype;  /* message type */ 
    char  mtext[1]; /* message text */ 
} 

的問題是,你包括mtype構件(4個字節)的大小,以便msgrcv()在結構堆棧的末尾寫入了四個字節。