0

我有代码从第一次迭代时崩溃的套接字接收字符串数据:

int size_data = 1024*sizeof(char);              
char *data = malloc(size_data);
char *data_aux;
int br_aux=0;
int *nptr;

memset(&data[0], 0, size_data);
int br = recv(sockdata, data, size_data, 0);
data_aux = malloc(br);
while (br>0) {
  br_aux = br_aux + br;
  strcat(data_aux, data);
  br = recv(sockdata,data, size_data, 0);
  if (br > 0) {
    nptr = (int *) realloc(data_aux, br+br_aux);
  }
}
free(data);
printf("%s", data_aux);
free(data_aux);

没什么复杂的,但是我得到一个错误:

* 检测到 glibc./clientFTP: free(): invalid next size (normal): 0x00000000061d6420 * * ======= 回溯:========= /lib64/libc.so.6[0x366be7247f] /lib64/ libc.so.6(cfree+0x4b)[0x366be728db] ./clientFTP[0x401e39] /lib64/libc.so.6(__libc_start_main+0xf4)[0x366be1d9b4] ./clientFTP[0x400b89] ======= 内存映射: ======== 00400000-00403000 r-xp 00000000 fd:00 5396214 /home/alumno/FTP/clientFTP 00602000-00603000 rw-p 00002000 fd:00 5396214
/home/alumno/FTP/clientFTP17006d 0601 rw-p 061d6000 00:00 0
[堆] 366ba00000-366ba1c000 r-xp 00000000 fd:00 1994999
/lib64/ld-2.5.so 366bc1c000-366bc1d000 r--p 0001c000 fd:06/ ld:
069 366bc1d000-366bc1e000 rw-p 0001d000 fd:00 1994999
/lib64/ld-2.5.so 366be00000-366bf4e000 r-xp 00000000 fd:00 1995001
/lib64/libc-2.5.so 366bf4e000-366c14e000 ---p 0014e000 fd:00 1995001
/lib64/libc-2.5.so 366c14e000-366c152000 r--p 0014e000 fd:00 1995001
/lib64/libc-2.5.so 366c152000-366c153000 rw-p 00152000 fd:00 1995001
/lib64/libc-2.5.so 366c153000-366c158000 rw-p 366c153000 00:00 0 3672200000-367220d000 r-xp 00000000 fd:00 1995011
/lib64/libgcc_s-4.1.2-20080825.so.1 367220d000-367240d000 ---p 0000d000 fd:00 1995011
/lib64/libgcc_s-4.0.2-2007208 20072082 367240e000 rw-p 0000d000 fd:00 1995011
/lib64/libgcc_s-4.1.2-20080825.so.1 2b5cdf8d9000-2b5cdf8dd000 rw-p 2b5cdf8d9000 00:00 0 2b5cdf8f6000-2b5cdf8f7000 rw-p 2b5cdf8f6000 00:00 0 7fffae47e000-7fffae493000 rw-p 7ffffffe9000 00:00 0
[stack] 7fffae5fc000-7fffae600000 r-xp 7fffae5fc000 00:00 0
[vdso] ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0
[vsyscall] 中止

4

5 回答 5

2

有两个不同的问题。

一、线

nptr = (int *)realloc(data_aux,(br+br_aux));

做三件事:

  1. 它尝试分配br + br_aux字节。
  2. 它可以释放data_aux指向的内存。
  3. 它指向nptr新分配的内存地址。

但是代码继续使用data_aux,就好像它仍然指向新内存一样。

其次,由于recv()返回接收到的字节数,您应该使用该信息将数据附加到缓冲区:

while (br > 0) {
  memcpy(data_aux + br_aux, data, br);
  br_aux += br;
  br = recv(sockdata, data, size_data, 0);
  if (br > 0) {
    nptr = (int *) realloc(data_aux, br + br_aux);
    if (nptr == NULL) {
      // ERROR
    }
    data_aux = nptr;
  }
}

recv()与任何字符串操作(如 )结合使用的问题strcat()recv()可以返回二进制数据。如果该数据恰好包含零字节,则字符串函数将假定它是数据的结尾,并以您既不期望也不想要的方式运行。

实际上还有第三个问题,即没有检查任何返回值是否有错误。 总是检查错误,而不是假设内存是有效的,或者 socked 通信已经成功。

于 2012-05-16T01:59:10.107 回答
1

代码中有很多问题,但我会解决大问题:

  1. 您正在分配内存并假设它已准备好使用:

    data_aux = malloc(br);
    ...
    strcat(data_aux, data); /* <- who said data_aux isn't garbage? */
    
  2. 您应该考虑realloc移动数据或调用本身失败data_aux不够大的情况:

    成功完成后,大小不等于 0,realloc()返回指向(可能已移动)分配空间的指针。如果 size 为 0,则返回可以成功传递的空指针或唯一指针free()。如果没有足够的可用内存,则realloc()返回一个空指针并设置errnoENOMEM.

    data_aux = realloc(data_aux, br + br_aux); /* reassign data_aux */
    
  3. 您没有检查任何返回值。一个大的不是recv()在分配内存之前检查结果:

    br = recv(...);
    ...
    data_aux = malloc(br); /* -1 as a size is large in unsigned speak */
    
  4. 您正在对可能不包含chars 的数据使用 ASCIIZ 字符串函数。使用memcpy代替strcator strncat

于 2012-05-16T01:55:31.117 回答
0

如果realloc()成功,则输入的内存块不再有效,返回的指针指向新的内存块。如果realloc()失败,输入内存块仍然有效。您将返回的指针分配给一个nptr根本不用于任何事情的变量,并且您永远不会更新该data_aux变量以指向重新分配的内存。当您调用free()freedata_aux时,如果realloc()事先调用并成功,您将释放错误的指针,这可能会导致您看到的崩溃。

改变这个:

nptr = (int *) realloc(data_aux,(br+br_aux)); 

为此:

nptr = (char*)realloc(data_aux, br_aux + br); 
if (!nptr)
{
    ... error handling ...
    break;
}
data_aux = nptr;

话虽如此,您应该将整个逻辑重写为更像以下内容。循环中无需recv()多次调用:

int size_data = 1024 * sizeof(char);                
char *data_aux = NULL;
int br_aux = 0;  
char *nptr;  

char *data = malloc(size_data);  
if (data)
{
    int br = recv(sockdata, data, size_data, 0);
    while (br > 0)
    {  
        nptr = (char*) realloc(data_aux, br_aux + br);
        if (!nptr)
            break;

        data_aux = nptr;
        memcpy(&data_aux[br_aux], data, br);  
        br_aux = br_aux + br;  
    }  

    free(data);  
}

printf("%.*s", br_aux, data_aux);  
free(data_aux);  

为了进一步简化,将data缓冲区放在堆栈上:

char* data_aux = NULL;
int br_aux = 0;  

char data[1024];
char *nptr;  

int br = recv(sockdata, data, sizeof(data), 0);
while (br > 0)
{  
    nptr = (char*) realloc(data_aux, br_aux + br);
    if (!nptr)
        break;

    data_aux = nptr;
    memcpy(&data_aux[br_aux], data, br);  
    br_aux = br_aux + br;  
}  

printf("%.*s", br_aux, data_aux);  
free(data_aux);  
于 2012-05-16T02:12:24.547 回答
0

呃 - 您从套接字收到的字符串是否以空值结尾?

建议:

  1. 确保在发送之前在消息中包含空字节

  2. 使用 strncat()

  3. 如有必要,请自行终止缓冲区

PS:我猜你正在超出“strcat(data_aux)”中的缓冲区,这会无意中破坏“data”和“data_aux”。

于 2012-05-16T01:47:05.473 回答
0
data_aux = malloc(br);   //data_aux may not filled with zero
//data_aux[0] = '\o';

while (br>0)
{
    br_aux = br_aux + br;  
    strcat(data_aux,data); //this may casue overflow, data may not end with '\0'
    br = recv(sockdata,data, size_data,0); 
    if(br>0)
    {
        //need check nptr is NULL? and size is (br + br_aux + 1), '\0' need one byte
        //nptr = (char*)realloc(data_aux,(br + br_aux + 1)); 
        nptr = (int *)realloc(data_aux,(br+br_aux)); 
        // if (nptr != NULL)
        //     data_aux = nptr;
        // else
        //     Error handling
    }
}
于 2012-05-16T02:39:43.030 回答