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

我有一个关于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 *)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)
    作为函数符号计算,而不是宏扩展
  • 指针设置为不可访问的值1。未使用值
    NULL
    (0),因为如果传递
    NULL
    ,则
    free()
    不会抱怨。传递“指针值”1应触发错误报告
    您可能会发现,在使用此宏之后,您的代码已经解除了对过时指针的保护。一旦您有了
    空闲的
    'd内存,指向它的指针将指向同一内存,并暂时指向内存中的相同值,直到第二次使用该内存时这些值被清除。因此,您的程序可能能够使用陈旧的指针运行几行。当指针过期时,将其更改为
    1
    将立即捕获此信息。

    @Tim:是的,在发送后立即释放它是安全的,不过您可能需要检查发送的返回值。它表示成功发送的字节数。我知道了,但是如果成功发送的所有字节和部分字节不成功,该怎么办?如果传递的大小为零,realloc()还可以释放从空闲存储分配的内存。否则,您是正确的——只有诸如free()和realloc()之类的堆API函数才能释放从空闲存储中获得的内存。