C语言是否会发送free buffer方法?

7
我有一个关于 C 语言 send 方法的问题。
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);

我想知道是我自己释放缓冲区,还是发送方法会释放它?这与it技术有关。

以下是我释放缓冲区的代码:

char *buffer = (char *)malloc(100*sizeof(char));
send(s, buffer, 100*sizeof(char), MSG_NOSIGNAL);
free(buffer);

当我看到这个错误时,我认为我释放缓冲区太快了,而发送方法仍在使用内存。请告诉我。
5个回答

8

send函数不会释放缓冲区,你需要手动释放。除了它本来就没有被设计成这样(套接字函数与堆函数是独立的),send也无法“知道”是否应该释放内存,因为它可能是指向已分配内存块中间的指针,也可能是指向栈数据的指针。

在调用send后立即释放缓冲区应该是“安全”的,因为该函数将把数据复制到其自己的内部缓冲区中。您展示的代码不会导致损坏问题(尽管我怀疑涉及更多代码,因为缓冲区未按所示进行初始化)。在进程早期堆被破坏并且直到后来才导致异常(例如,在send之后的free)也是可能的。

send的返回值表示成功发送的字节数(虽然不一定成功传递)。因此,虽然释放缓冲区是“安全”的,但如果未完全发送所有数据,则会丢失未发送的数据。如果未发送整个缓冲区,则需要再次使用剩余的数量调用send


1
@Tim:是的,在发送后释放它应该是安全的,不过你可能需要检查send的返回值。它表示成功发送的字节数。 - Mark Wilkins
我明白了,但如果所有字节都成功发送怎么办?如果有一些字节没有发送成功呢? - Tim

1

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

0

从你的描述来看,似乎你的代码在释放指针后仍在使用它,导致出现了问题。有一些可靠的方法可以解决这种问题,也有一些快速的技巧。以下是一个快速的技巧:

#define free(p) do { (free)(p); p=(void*)1; } while (0)

这个宏应该包含在您的头文件或项目的第一行中,以替换您对free的调用,以便:

  1. 内存仍然被释放,符号(free)(p)强制C编译器将(free)评估为函数符号,而不是宏扩展。
  2. 指针设置为不可访问的值1。没有使用NULL(0)的值,因为如果传递NULL,free()不会抱怨。传递一个“指针值”为1应该触发错误报告。

您可能会发现,在使用此宏之后,您的代码已经解引用了过时的指针。一旦您释放了内存,指向它的指针将指向相同的内存,并且暂时将指向内存中的相同值--直到第二次使用该内存清除这些值。因此,您的程序可能能够使用过时的指针运行几行。当指针变得陈旧时,将每个指针更改为1将立即捕获此问题。


0

send()函数不会释放缓冲区。如果您遇到双重释放问题,您应该检查您释放的位置以及如何到达该位置。


0

一般来说,如果一个API函数释放缓冲区,那将是非常不寻常的。我所知道唯一会释放缓冲区的函数是"free"...

有时候,函数会分配内存,你必须在使用完它们后释放,例如strdup。

有些函数在使用后不能直接释放缓冲区。例如,在.NET中,如果位图数据指针仍在位图包装器中使用,则无法处理位图的数据指针。


realloc()函数如果传入大小为零的参数,也可以释放从自由存储区分配的内存。否则,您是正确的——只有堆API函数,如free()和realloc(),才能释放从自由存储区获得的内存。 - Heath Hunnicutt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接