我正在尝试显示缓冲区,但它正在显示特殊字符。这是我的代码:
size_t write(int fd, const void *buf, size_t count)
{
static size_t (*write_func)(int, const void *, size_t) = NULL;
if (!write_func)
write_func = (size_t(*)(int, const void *, size_t)) dlsym(RTLD_NEXT, "write");
char tmp[count];
memcpy(tmp,buf,count);
printf(" %c \n",tmp[1]);
您对如何解决此问题有任何想法吗?非常感谢你!
答案 0 :(得分:0)
您在堆栈上分配只读数据的副本。这很危险,因为堆栈空间可能有限。 (在Linux中,只有原始堆栈会动态增长;线程堆栈的大小固定,通常非常小。)
然后使用stdio.h printf()
函数将指定数据的第二个字节(即使count
可能是1)输出到标准输出,因此您可能会访问无论如何临时阵列。
大多数printf()
实现在内部调用write()
来刷新缓冲区。根据链接,这可能最终是递归的(您的函数调用printf
调用您的函数调用printf
等),耗尽进程可用的所有RAM,然后崩溃。
以上都没有意义。
首先,如果您需要复制输入数据,请使用malloc()
和memcpy()
动态执行,然后再使用free()
。这样你就不会突然开始在多线程程序中造成崩溃(除了Linux中的原始进程之外,堆栈空间是有限的并且已经修复了所有这些)。
其次,您需要使用使用链接器获得的原始write_func
。
第三,您需要保留errno
以避免客户端程序中出现无法预料的问题。只需使用临时本地int
即可存储它。请注意,不仅write()
,而且malloc()
和free()
可能会修改errno
,您必须隐藏调用者的这些更改。
第四,write()
的返回类型为ssize_t
,而不是size_t
。前者是签名的,后者可能是未签名的。
第五,总是允许短写。你永远不能依靠得到一个“完整”的块;应用程序执行内部处理,特别是在使用套接字时,以奇数大小(特别是TCP / IP和UDP / IP的MTU的倍数)刷新它。您对输入/输出的“修改”必须是无状态的。更糟糕的是,如果你的修改改变了缓冲区长度,并且描述符是非阻塞的,并且write_func()
调用返回一个简短的写入,只是在修改后的部分中间没有合理地映射到任何原始字节,你怎么样处理它?真的,你不能重试,因为描述符是非阻塞的;原始应用程序可能会挂起 - 例如,如果以协处理方式使用,同时从具有严格排序要求的对等进程发送和接收数据 - 因为当在应用程序逻辑级别不允许写入时,您的添加将重新发出写入。 / p>
简单地说,你的计划不会起作用。您可能会使用某些特定的简单应用程序,但它可以打破其他可怕的应用程序。无论你想要实现什么,都有更好的方法。
我希望我不是太生硬,但我认真地建议你先创建低级POSIX I / O的细节,然后再创建包装器。 Linux man-pages project是我推荐的一个很好的参考,但我想你可能需要先从一些教程开始。