Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 指针在多线程函数中声明后不久被释放_Multithreading_Thread Safety_Access Violation_Corruption - Fatal编程技术网

Multithreading 指针在多线程函数中声明后不久被释放

Multithreading 指针在多线程函数中声明后不久被释放,multithreading,thread-safety,access-violation,corruption,Multithreading,Thread Safety,Access Violation,Corruption,我目前在我的一些代码中遇到了一个非常奇怪的问题。一个变量在声明后似乎没有问题,但在声明后立即损坏,并导致访问冲突(基本上指针仍指向同一位置,但内存似乎未分配)。我很确定这个问题与多线程有关,但我不知道它是什么,因为我对多线程相当陌生 代码如下: #include "Firewall.h" #include <Ws2tcpip.h> Firewall::Firewall(void) { } Firewall::~Firewall(void) { } void Firewall:

我目前在我的一些代码中遇到了一个非常奇怪的问题。一个变量在声明后似乎没有问题,但在声明后立即损坏,并导致访问冲突(基本上指针仍指向同一位置,但内存似乎未分配)。我很确定这个问题与多线程有关,但我不知道它是什么,因为我对多线程相当陌生

代码如下:

#include "Firewall.h"
#include <Ws2tcpip.h>

Firewall::Firewall(void)
{
}


Firewall::~Firewall(void)
{
}

void Firewall::parseFile(string filePath)
{
    XMLNode xMainNode=XMLNode::openFileHelper(filePath.c_str(),"firewall");

    // Filtrage
    XMLNode nodeFiltrage = xMainNode.getChildNode("filtrage");
    XMLNode currentNode;

    for(int i=0; i < nodeFiltrage.nChildNode();i++)
    {
        currentNode = nodeFiltrage.getChildNode(i);

        string nom = currentNode.getName();

        if(nom == "permettre")
            mapFiltrage_.insert(pair<int,bool>(atoi(currentNode.getAttribute().lpszValue), true));

        else if(nom == "bloquer")
            mapFiltrage_.insert(pair<int,bool>(atoi(currentNode.getAttribute().lpszValue), false));
    }

    // Redirection

    XMLNode nodeRedirection = xMainNode.getChildNode("redirection");
    XMLNode currentSubNode;

    for(int i = 0; i < nodeRedirection.nChildNode(); i++)
    {
        currentNode = nodeRedirection.getChildNode(i);
        currentSubNode = currentNode.getChildNode("source");

        SourceDestination source((string)currentSubNode.getAttribute("adresse"), atoi(currentSubNode.getAttribute("port")));

        currentSubNode = currentNode.getChildNode("destination");
        SourceDestination destination((string)currentSubNode.getAttribute("adresse"), atoi(currentSubNode.getAttribute("port")));

        mapRedirection_.insert(pair<SourceDestination, SourceDestination>(source,destination)); 

        pair<SourceDestination, SourceDestination> test;
    }


}

void Firewall::initialiser()
{
    std::map<int, bool>::iterator iterFiltrage = mapFiltrage_.begin();
    HANDLE handleThread;

    std::string tempFiltrage = "localhost";
    thread_arg arg;

    // Parcours et lancement des connexions de filtrage
    while(iterFiltrage != mapFiltrage_.end())
    {
        arg.port = (*iterFiltrage).first;
        arg.host = tempFiltrage;
        arg.objRef = this;

        handleThread = CreateThread(NULL, 0, listenThread, &arg, 0, NULL);
        listeThread_.push_back(handleThread);

        iterFiltrage++;
    }

    // Parcours et lancement des connexions de redirection
    std::map<SourceDestination, SourceDestination>::iterator iterRedirection = mapRedirection_.begin();

    while(iterRedirection != mapRedirection_.end())
    {
        // Éviter la duplication inutile des sockets
        if(mapFiltrage_.find((*iterRedirection).first.Port()) == mapFiltrage_.end())
        {
            arg.host =  (*iterRedirection).first.Host();
            arg.port = (*iterRedirection).first.Port();
            arg.objRef = this;

            handleThread = CreateThread(NULL, 0, listenThread, &arg, 0, NULL);
            listeThread_.push_back(handleThread);
        }

        iterRedirection++;
    }
}


DWORD WINAPI Firewall::listenThread(LPVOID lpParam)
{
    thread_arg* temp = (thread_arg*)lpParam;
    Firewall* firewallRef = temp->objRef;

    return firewallRef->runThread(lpParam);
}

DWORD Firewall::runThread( LPVOID lpParam )
{
    thread_arg* infosSocket = (thread_arg*)lpParam;

    // Créer le socket et l'attacher à la source
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);

    if(sock == INVALID_SOCKET)
    {
        cout << "Erreur de creation de socket" << endl;
        return EXIT_FAILURE;
    }

    //Recuperation de l'adresse locale
    hostent *thisHost;
    const char* test = infosSocket->host.c_str();
    thisHost=gethostbyname(test);
    char* ip;
    ip=inet_ntoa(*(struct in_addr*) *thisHost->h_addr_list);

    SOCKADDR_IN sin;
    sin.sin_addr.s_addr = inet_addr(ip);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(infosSocket->port);



    if(bind(sock, (SOCKADDR*)&sin, sizeof(sin)) == SOCKET_ERROR)
    {
        cout << "Erreur de binding" << endl;
        return EXIT_FAILURE;
    }

    // Contexte du client
    SOCKADDR_IN csin;
    SOCKET csock;
    socklen_t crecsize = sizeof(csin);

    listeSocket_.push_back(sock);
    listeSocket_.push_back(csock);

    // Écouter sur le port
    if(listen(sock, 5) == SOCKET_ERROR)
    {
        cout << "Erreur de listen" << endl;
        return EXIT_FAILURE;
    }

    //csock = accept(sock, (SOCKADDR*)&csin, &crecsize);

    return EXIT_SUCCESS;
}

void Firewall::quitter()
{
    // Fermer les sockets
    vector<SOCKET>::iterator iter1 = listeSocket_.begin();

    while(iter1 != listeSocket_.end())
    {
        closesocket((*iter1));
        iter1++;
    }

    // Fermer les threads

    vector<HANDLE>::iterator iter2 = listeThread_.begin();

    while(iter2 != listeThread_.end())
    {
        TerminateThread((*iter2), EXIT_SUCCESS);
        CloseHandle((*iter2));
    }
}
#包括“Firewall.h”
#包括
防火墙::防火墙(无效)
{
}
防火墙::~防火墙(无效)
{
}
无效防火墙::解析文件(字符串文件路径)
{
XMLNode xMainNode=XMLNode::openFileHelper(filePath.c_str(),“防火墙”);
//过滤
XMLNode nodeFiltrage=xMainNode.getChildNode(“过滤”);
XMLNode当前节点;
对于(int i=0;iobjRef;
返回firewallRef->runThread(lpParam);
}
DWORD防火墙::运行线程(LPVOID lpParam)
{
thread_arg*infosSocket=(thread_arg*)lpParam;
//电源插座和附件
SOCKET sock=SOCKET(AF\u INET,sock\u STREAM,0);
if(sock==无效的_套接字)
{

cout您的问题在以下代码中:

thread_arg arg;

loop(...)
{
    arg = ...;
    handleThread = CreateThread(..., &arg, ...);
}
在这里启动的每个线程都会收到同一个thread_arg实例的地址。然后,为了启动下一个线程,您再次在先前启动的线程的底部修改该实例。作为补救措施,请创建一个包含必要参数(主机、端口、此)的结构将此结构存储在std::list中,然后将相应元素的地址传递给CreateThread()

代码中还有一个问题,您应该检查returnvalues。如果您知道已检测到所有明显的错误,最好在某些代码上寻求帮助。为此,最容易使用异常。在CreateThread()之后(可能是beginthread()),添加以下行:

if(handleThread == NULL)
    throw std::runtime_error("CreateThread() failed");
在第二步中,创建一个从runtime_error派生的专用异常类,该类保存win32错误代码(请参见GetLastError()),并在异常消息中包含文本错误描述(请参见FormatString())。这听起来像是一大堆代码,但您只需编写一次,就可以在许多地方重用它

最后,quitter()有两个问题。第一个是无限循环。如果关闭句柄后不需要它们,请尝试以下操作:

for(; listeThread_.empty(); listeTread_.pop_back())
{
    TerminateThread(listeThread_.back(), EXIT_SUCCESS);
    CloseHandle(listeThread_.back());
}

您也可以将其编写为while循环,但如果迭代次数基本固定,我个人更喜欢for循环。当然,您仍然需要检查TerminateThread()和CloseHandle()的返回值。第二个问题是TerminateThread()这是一个坏主意,因为你可能在半成品的中间终止线程。在Web上搜索“终止线程有害”。在这里,你可以做的就是等待它使用WaIfFutSunLobObjor()结束。.

非常感谢您的提示。也感谢您花时间查看代码的其余部分,并指出我犯的一些其他错误。