对小文件使用读取时堆栈溢出的说明和有问题的解决方法

发布于 2024-08-09 12:16:27 字数 821 浏览 13 评论 0原文

我希望这个问题能解释我的问题。如果能解释“有效”的解决方法,我也将不胜感激。

读取文件的传统方式(据我所知)

int fd;
char buffer[MAX];
while(read(fd,buffer,MAX)>0)
{
         buffer[MAX]='\0';
         write(sockfd,buffer,MAX);
         memset(buffer,NULL,MAX);
}

会导致溢出。不知何故出乎意料地起作用的解决方法是

   while((read(fd,buffer,MAX)!=0)||(read(fd,buffer,MAX)!= -1))
   {
         buffer[MAX]='\0';
         write(sockfd,buffer,MAX);
         memset(buffer,NULL,MAX);

   }

^^ 此代码打印出整个文件,据观察没有跳过。

诸如此类的事情

do
{
     int temp;
     temp=read(fd,buffer,MAX);
     if((temp == 0) || (temp == -1))
     {
              break;
     }
     buffer[MAX]='\0';
     write(sockfd,buffer,MAX);
     memset(buffer,NULL,MAX);
 }while(1);

也导致了堆栈溢出。我在这里错过了一些真正重要的东西吗?

谢谢

I hope the question explained my problem. I would also be grateful if the workaround that "works" is explained.

The traditional way of reading a file (that i know of)

int fd;
char buffer[MAX];
while(read(fd,buffer,MAX)>0)
{
         buffer[MAX]='\0';
         write(sockfd,buffer,MAX);
         memset(buffer,NULL,MAX);
}

was causing an overflow. The workaround that somehow unexpectedly worked was

   while((read(fd,buffer,MAX)!=0)||(read(fd,buffer,MAX)!= -1))
   {
         buffer[MAX]='\0';
         write(sockfd,buffer,MAX);
         memset(buffer,NULL,MAX);

   }

^^ This code printed out the entire file, no skips as far as observable.

Things like

do
{
     int temp;
     temp=read(fd,buffer,MAX);
     if((temp == 0) || (temp == -1))
     {
              break;
     }
     buffer[MAX]='\0';
     write(sockfd,buffer,MAX);
     memset(buffer,NULL,MAX);
 }while(1);

also caused a stack overflow. Am i missing something really important here?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

冰之心 2024-08-16 12:16:27

为什么说它会造成溢出呢?

请注意,read() 不会在 char 数组的末尾写入 \0,因此,如果您执行类似 的操作, printf("%s", buffer) 它可能会失败,因为 printf 将期待一个 NUL 终止的字符串。您可能想要读取 MAX-1 并设置 buffer[number_of_read_characters] = '\0',其中 number_of_read_charactersread( ) 返回,如果是肯定的。

另请注意,当您声明 char buffer[MAX] 时,由于 C 索引是从零开始的,因此最高 buffer 索引为 MAX-1 ,因此当您设置 buffer[MAX]='\0' 时,您已经超出了数组范围。

Why do you say that it's causing an overflow?

Do note that read() will not write a \0 in the end of the char array, so if you do something like printf("%s", buffer) it will likely fail because printf will be expecting a NUL terminated string. You may be wanting to read MAX-1 and set buffer[number_of_read_characters] = '\0' where number_of_read_characters is whatever read() returned, if positive.

Also note that when you declare char buffer[MAX], since in C indexing is zero-based, the highest buffer index is MAX-1, so when you're setting buffer[MAX]='\0' you're already out of your array bounds.

木格 2024-08-16 12:16:27

一个问题:

buffer[MAX]='\0';

在堆栈上执行步骤,因为大小为 MAX 的数组的最高有效索引是 MAX-1(由于基于 0 的索引)。

read 的返回值 -1 表示错误,因此测试 read() > 的正确方法是: 0。此外,read 的正常返回值是读取的字节数,并且 read 不保证任何 0 终止。你必须按照以下方式做一些事情

while (bytesRead=read() > 0) {
    write(buffer, bytesRead);
...

One problem:

buffer[MAX]='\0';

steps on stack, as the highest valid index for array of size MAX is MAX-1 (due to 0-based indexes).

-1 return value from read indicates an error, so the right thing to test read() > 0. Moreover, the normal return value from read is the number of bytes read, and read does not guarantee any 0-termination. you have to do someting along the lines of

while (bytesRead=read() > 0) {
    write(buffer, bytesRead);
...
诗笺 2024-08-16 12:16:27

看了一眼代码,我认为这是因为逻辑不同。

在有效的示例中,read(fd,buffer,MAX) 方法被执行两次。

可以这样想:

while (dosomething() != 0 || dosomething() != -1)
{
    // some work
}

如果 dosomething() 方法是幂等的,则该循环将是无限的,但是如果第一次在 while 语句中运行它与第二次不同,它将中断。

这解释了执行路径的不同之处,但我无法弄清楚为什么第一个选项会溢出......我会考虑并更新。 (或者没有 - 似乎已经得到了回答!)

Glancing at the code, I'd suggest that it's because the logic is different.

In the example that works, the read(fd,buffer,MAX) method is being executed twice.

Think of it like:

while (dosomething() != 0 || dosomething() != -1)
{
    // some work
}

This loop will be infinite if the dosomething() method is idempotent, however if the first time you run it within the while statement is different than the second, it will break.

That explains how the execution path differs, but I can't figure out why the first option overflows... I'll think about it and update. (or not - it seems it's been answered!)

相思故 2024-08-16 12:16:27

试试这个:

int fd, readCharacter;
char buffer[MAX];
while( readCharacter = read(fd, buffer, MAX**-1**) > 0 )
{
    buffer[readCharacter] = '\0';
    // ...
}

Try this:

int fd, readCharacter;
char buffer[MAX];
while( readCharacter = read(fd, buffer, MAX**-1**) > 0 )
{
    buffer[readCharacter] = '\0';
    // ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文