我有代码从第一次迭代崩溃的套接字接收字符串数据:
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():无效的下一个尺寸(正常):0x00000000061d6420 * * ======= Backtrace:========= / 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 / clientFTP 061d6000-061f7000 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:00 1994999
/lib64/ld-2.5.so 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.1.2-20080825.so.1 367240d000-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]已中止
答案 0 :(得分:2)
有两个不同的问题。
首先,行
nptr = (int *)realloc(data_aux,(br+br_aux));
做了三件事:
br + br_aux
个字节。data_aux
指向的内存。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通信成功。
答案 1 :(得分:1)
代码中存在许多问题,但我会解决大问题:
您正在分配内存并假设它已准备就绪:
data_aux = malloc(br);
...
strcat(data_aux, data); /* <- who said data_aux isn't garbage? */
您应该考虑realloc
has moved your data or when the call itself fails和data_aux
不够大的情况:
成功完成且大小不等于0时,
realloc()
返回指向(可能已移动)分配空间的指针。如果size为0,则返回空指针或可成功传递给free()
的唯一指针。如果没有足够的可用内存,realloc()
将返回空指针并将errno
设置为ENOMEM
。
data_aux = realloc(data_aux, br + br_aux); /* reassign data_aux */
您没有检查任何返回值。一个大的不是在用它分配内存之前检查recv()
的结果:
br = recv(...);
...
data_aux = malloc(br); /* -1 as a size is large in unsigned speak */
您正在对可能甚至不包含char
的数据使用ASCIIZ字符串函数。使用memcpy
代替strcat
或strncat
。
答案 2 :(得分:0)
呃 - 是你从socket null接收的字符串?
建议:
确保在发送之前在邮件中包含空字节
使用strncat()
如有必要,Null自行终止缓冲区
PS: 我猜你在“strcat(data_aux)”中占用了缓冲区,这无意中破坏了“数据”和“data_aux”。
答案 3 :(得分:0)
如果realloc()
成功,则输入内存块不再有效,返回的指针指向新的内存块。如果realloc()
失败,则输入内存块仍然有效。您将返回的指针分配给一个根本不用于任何内容的nptr
变量,并且您永远不会更新data_aux
变量以指向重新分配的内存。当您致电free()
以免费data_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);
答案 4 :(得分: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
}
}