简体   繁体   English

C ++动态数组在分配时导致分段错误

[英]C++ dynamic array causes segmentation fault at assignment

I am doing a application witch uses sockets so I am holding in an array the sockets handles.I have the following code: 我正在做一个使用套接字的应用程序,所以我将套接字句柄保存在数组中。我有以下代码:

while(0 == 0){
    int * tx = (int*)(malloc((nr_con + 2) * sizeof(int)));
    if (conexiuni != NULL)
    {
        syslog(LOG_NOTICE,"Ajung la eliberare %d",nr_con);
        memcpy(&tx[0],&conexiuni[0],(sizeof(int) * (nr_con)));
        syslog(LOG_NOTICE,"Ajung la eliberare %d",nr_con);
        free(conexiuni);
    }
    conexiuni = tx;

    syslog(LOG_NOTICE,"Ajung la mama %d",nr_con);
    //The line bellow causes a segfault at second connection
    if ((conexiuni[nr_con] = accept(hsock,(sockaddr*)(&sadr),&addr_size)) != -1)
    {
        nr_con++;
        syslog(LOG_NOTICE,"Primesc de la %s",inet_ntoa(sadr.sin_addr));
        syslog(LOG_NOTICE,"kkt %d",conexiuni[nr_con - 1]);
        int * sz = (int*)malloc(sizeof(int));
        *sz = conexiuni[nr_con - 1];
        syslog(LOG_NOTICE,"after %d",*sz);
        pthread_create(&tidi,0,&ConexiuniHandler, sz);
    }
}

When I connect the second time when I assign the array the program crashes. 当我第二次分配数组时连接时,程序崩溃。 What am I doing wrong? 我究竟做错了什么? I tried the same code on Windows and it works well but on Linux it crashes. 我在Windows上尝试了相同的代码,但效果很好,但在Linux上崩溃了。

Use a std::vector . 使用std::vector

Oops! 糟糕! Your answer couldn't be submitted because: 由于以下原因,您的答案无法提交:
body must be at least 30 characters; 正文必须至少包含30个字符; you entered 19 您输入了19

I assume that what you are wanting to do is to have a server that is accepting connections and then as the connections are accepted, you start a thread to handle that connection request. 我假设您要做的是拥有一台接受连接的服务器,然后在接受连接时,您启动一​​个线程来处理该连接请求。 So each time you do an accept you are wanting to start up a thread and give it the socket handle. 因此,每次执行接受操作时,您都想启动一个线程并为其提供套接字句柄。 You are also keeping up with all of the socket handles in an array which is dynamically increased as you accept new connection requests. 您还需要跟上阵列中的所有套接字句柄,当您接受新的连接请求时,该数组会动态增加。

Following is a suggested method. 以下是建议的方法。 I have not done any testing nor have I even compiled this code segment however it is a place to start. 我没有做任何测试,甚至没有编译过此代码段,但这是一个起点。 One thing that I am doing is increasing the array of socket handles by blocks of 16 each time I do a resize of the array. 我正在做的一件事是每次我调整数组大小时,将套接字句柄数组增加16个块。 I am doing this because it can make the job of the memory manager a bit easier and reduce the amount of fragmentation by reducing the number of calls to malloc() . 我这样做是因为它可以使内存管理器的工作更加轻松,并通过减少对malloc()的调用次数来减少碎片的数量。

int nr_con = 0;      // we start off with no connections
int block_con = 16;  // number of blocks to allocate each time we increase the array
SOCKET  *conexiuni = malloc ((nr_con + block_con) * sizeof(SOCKET));
while(1) {
    syslog (LOG_NOTICE, "Ajung la mama %d", nr_con);

    // wait for a connection request to come in.  if it does, log the request
    // then create a thread to handle the request providing the socket to the thread.
    // we are keeping an array of the sockets that is dynamically increased so
    // we will allocate blocks of 16 at a time as we lengthen the array.
    if ((conexiuni[nr_con] = accept (hsock, (sockaddr*)(&sadr), &addr_size)) != -1)
    {
        block_con--;
        if (block_con < 1) {
        {
            // so lets add another block to our array by allocating the memory
            // then copying the current array to the new memory area then freeing
            // the old memory area which is no longer needed.
            block_con = 16;
            SOCKET *pTemp = malloc(nr_con + block_con) * sizeof(SOCKET));
            syslog (LOG_NOTICE, "Ajung la eliberare %d", nr_con);
            memcpy (pTemp, conexiuni, (sizeof(SOCKET) * (nr_con + 1)));
            syslog (LOG_NOTICE, "Ajung la eliberare %d", nr_con);
            free (conexiuni);
            conexiuni = pTemp;
        }
        syslog (LOG_NOTICE, "Primesc de la %s", inet_ntoa(sadr.sin_addr));
        syslog (LOG_NOTICE, "kkt %d", conexiuni[nr_con]);

        SOCKET  *sz = conexiumi + nr_con;
        syslog (LOG_NOTICE, "after %d", *sz);

        // start the thread which is to service this connection request.
        pthread_create (&tidi, 0, &ConexiuniHandler, sz);
        nr_con++;
    }
}

However there are a few issues with something like this. 但是,类似这样的问题。 First of all in the example above I am not handling an out of memory error should malloc() return a NULL pointer due to being unable to provide the memory request. 首先,在上面的示例中,由于无法提供内存请求,因此malloc()返回NULL指针,因此我不处理内存不足错误。

The second issue is the possibility that the thread will not access the pointer to the socket before the array is dynamically extended rendering the pointer provided invalid since it was freed during the dynamic reallocation. 第二个问题是线程可能无法在动态扩展数组之前访问指向套接字的指针,从而使所提供的指针无效,因为在动态重新分配期间已将其释放。 So if you have lots of connections coming in quickly, this may be a problem. 因此,如果您有许多快速进入的连接,则可能是一个问题。 At a minimum the first thing the thread should do is make a local copy of the socket handle. 线程至少应该做的第一件事是对套接字句柄进行本地复制。

Another question is how are you going to go back over the array to determine which sockets are still valid and open and which are stale with the connection closed. 另一个问题是,您将如何返回阵列以确定哪些套接字仍然有效并处于打开状态,哪些套接字在关闭连接后已失效。 Do you just keep dynamically allocating space as connection requests come in until you run out of memory after a few days of your server being up and running? 在服务器启动并运行几天后,随着连接请求的到来,您是否一直保持动态分配空间,直到内存用完为止?

Rather than using int, you really should be using SOCKET since that it the actual data type. 实际上,应该使用SOCKET而不是使用int,因为它是实际的数据类型。 I realize that in most cases, a SOCKET is actually an int, however it is usually better to be precise in these matters. 我意识到,在大多数情况下,SOCKET实际上是一个int,但是在这些问题上通常更精确一些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM