C发送方法释放缓冲区吗?
我有一个关于C的发送方法的问题C发送方法释放缓冲区吗?,c,free,send,C,Free,Send,我有一个关于C的发送方法的问题 int send (int socket, void *buffer, size_t size, int flags); 我的代码: char *buffer = (char *)malloc(100*sizeof(char)); send(s, buffer, 100*sizeof(char), MSG_NOSIGNAL); 现在我想知道我是应该自己释放缓冲区,还是send方法释放缓冲区 释放缓冲区的代码: char *buffer = (char *)ma
int send (int socket, void *buffer, size_t size, int flags);
我的代码:
char *buffer = (char *)malloc(100*sizeof(char));
send(s, buffer, 100*sizeof(char), MSG_NOSIGNAL);
现在我想知道我是应该自己释放缓冲区,还是send方法释放缓冲区
释放缓冲区的代码:
char *buffer = (char *)malloc(100*sizeof(char));
send(s, buffer, 100*sizeof(char), MSG_NOSIGNAL);
free(buffer);
当我看到这个错误时,我想我很快就释放了缓冲区,send方法仍然在使用内存
让我知道。
发送
不会释放缓冲区。你需要释放它。除了它不是这样设计的(套接字函数独立于堆函数)之外,send实际上并不“知道”是否应该释放内存,因为它可能是指向已分配内存块中间的指针,也可能是指向堆栈数据的指针
在发送调用后立即释放缓冲区应该是“安全的”,因为函数将数据复制到自己的内部缓冲区。您显示的代码不会导致损坏问题(尽管我怀疑由于缓冲区未如图所示初始化,因此涉及的代码更多)。堆可能在进程的早期被损坏,直到稍后才会导致异常(例如,发送后的空闲时间)
send
的返回值表示成功发送的字节数(尽管不一定成功发送)。因此,虽然释放它是“安全的”,但如果未全部发送,您将丢失未发送的数据。如果未发送整个缓冲区,则需要使用剩余的数量再次调用send。send()不会释放缓冲区。如果您有双重释放问题,您应该查看您释放它的位置,并检查如何到达那里。您可以在发送
呼叫返回后释放
缓冲区,注意以下几点:
- 整个缓冲区可能尚未发送
- 该调用返回内核复制到自己缓冲区的字节数。剩下的你应该留着
char *buf; // sizeof(*buf) must be 1 for pointer arithmetic
ssize_t sent = send(fd, buf, len, 0);
if (sent != -1) { // no error
// move the unsent bytes to the start of the buffer
memmove(buf, buf + sent, len - sent);
// resize the buffer to fit the left over bytes
buf = realloc(buf, len - sent);
}
一般来说,如果api函数释放缓冲区,那将是非常不寻常的。我知道的唯一释放缓冲区的函数是“free” 有时,函数会分配使用后必须释放的内存,例如strdup
有些函数在使用后不能直接释放缓冲区。例如,在.Net中,如果位图的数据指针仍在位图包装器中使用,则无法对其进行处理 从您的描述听起来,好像您的代码在被释放后使用了指针。有好的、可靠的方法来解决这类问题,然后是快速的破解。下面是一个快速破解:
#define free(p) do { (free)(p); p=(void*)1; } while (0)
此宏(您希望包含在头文件或项目的第一行中)将替换对free的调用,以便:
free()
'd,符号(free)(p)
强制C编译器将(free)
作为函数符号计算,而不是宏扩展NULL
(0),因为如果传递NULL
,则free()
不会抱怨。传递“指针值”1应触发错误报告李>
您可能会发现,在使用此宏之后,您的代码已经解除了对过时指针的保护。一旦您有了
空闲的
'd内存,指向它的指针将指向同一内存,并暂时指向内存中的相同值,直到第二次使用该内存时这些值被清除。因此,您的程序可能能够使用陈旧的指针运行几行。当指针过期时,将其更改为1
将立即捕获此信息。@Tim:是的,在发送后立即释放它是安全的,不过您可能需要检查发送的返回值。它表示成功发送的字节数。我知道了,但是如果成功发送的所有字节和部分字节不成功,该怎么办?如果传递的大小为零,realloc()还可以释放从空闲存储分配的内存。否则,您是正确的——只有诸如free()和realloc()之类的堆API函数才能释放从空闲存储中获得的内存。