使用消息队列进行堆栈粉碎

时间:2012-01-04 18:47:22

标签: c++ stack message-queue

我有以下主要代码:

#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();

}
}

该代码用于测试我的通信平台。该平台运行良好,但是当Handler(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”后出现堆栈粉碎错误叫做。并且/ *更多代码* /中间是非重要代码,因为如果删除该部分,则会出现堆栈粉碎剧照。 经过大量调试后,我发现如果我打电话就会出现粉碎:

`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]

那么,有什么想法吗?如果您需要有关代码的信息,请问我。

1 个答案:

答案 0 :(得分:3)

根据thismsgsz的{​​{1}}参数应该是msgrcv()结构的mtext成员的大小:

mymsg

问题是你包含了struct mymsg { long int mtype; /* message type */ char mtext[1]; /* message text */ } 成员的大小(4个字节),所以mtype会在结构的末尾写入四个字节,这会破坏堆栈。