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

时间:2012-09-15 15:35:11

标签: c++ pointers segmentation-fault

我正在做一个使用套接字的应用程序,所以我在数组中保存套接字句柄。我有以下代码:

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);
    }
}

当我第二次连接分配数组时,程序崩溃了。我究竟做错了什么?我在Windows上尝试了相同的代码,它运行良好,但在Linux上崩溃。

2 个答案:

答案 0 :(得分:4)

使用std::vector

  

糟糕!您的答案无法提交,因为:
      身体必须至少30个字符;你进入了19

答案 1 :(得分:2)

我认为您想要做的是拥有一个接受连接的服务器,然后当接受连接时,您启动一​​个线程来处理该连接请求。因此,每次执行接受时,您都希望启动一个线程并为其提供套接字句柄。您还可以跟上数组中的所有套接字句柄,当您接受新的连接请求时,它会动态增加。

以下是建议的方法。我没有做任何测试,也没有编译这段代码,但它是一个开始的地方。我正在做的一件事是每次调整数组大小时,增加16个块的套接字句柄数组。我这样做是因为它可以使内存管理器的工作更容易,并通过减少对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++;
    }
}

然而,有一些类似的问题。首先,在上面的示例中,由于无法提供内存请求,malloc()返回NULL指针时,我没有处理内存不足错误。

第二个问题是线程在数组动态扩展之前不会访问指向套接字的指针,因为在动态重新分配期间释放了指针,因此提供的指针无效。因此,如果您有很多连接快速进入,这可能是一个问题。至少线程应该做的第一件事就是制作套接字句柄的本地副本。

另一个问题是,您将如何返回数组以确定哪些套接字仍然有效并且打开,哪些套接字关闭时过时。您是否只是在连接请求进入后动态分配空间,直到服务器启动并运行几天后内存不足为止?

您应该使用SOCKET而不是使用int,因为它是实际的数据类型。我意识到在大多数情况下,SOCKET实际上是一个int,但通常在这些问题上更精确。