为什么在 try 块内初始化文件指针会导致管道损坏?

发布于 2024-12-15 15:10:43 字数 787 浏览 4 评论 0原文

我有一个 bash 脚本,我正在从程序中读取结果。 Ptr 是一个简单的popen() 包装器。

bool getResult(const char* path){
  Ptr f(path);
  char buf[1024];
  while (fgets(buf, sizeof(buf), f) == 0) {
    if(errno == EINTR)
      continue;
    log.error("Error (%d) : %s",errno,path);
    return false;
  }
  ...
  return true;
}

这工作正常,但是 Ptr f(path) 不是异常安全的,所以我将其替换为:

Ptr f; // empty constructor, does nothing
char buf[1024];
try{
  Ptr f(path);
}catch(Exception& e){
  vlog.error("Could not open file at %s",path);
  return false;
}

运行时(并且文件存在)我收到以下错误:

/etc/my_script: line 165: echo: write error: Broken pipe

脚本的该行只是:

echo $result

到底是怎么回事?

I have a bash script which I'm reading the results from in my program. Ptr is a simple popen() wrapper.

bool getResult(const char* path){
  Ptr f(path);
  char buf[1024];
  while (fgets(buf, sizeof(buf), f) == 0) {
    if(errno == EINTR)
      continue;
    log.error("Error (%d) : %s",errno,path);
    return false;
  }
  ...
  return true;
}

This works fine, but Ptr f(path) is not exception safe, so I replace it with:

Ptr f; // empty constructor, does nothing
char buf[1024];
try{
  Ptr f(path);
}catch(Exception& e){
  vlog.error("Could not open file at %s",path);
  return false;
}

When run (and the file exists) I get the following error:

/etc/my_script: line 165: echo: write error: Broken pipe

That line of the script is just:

echo $result

What is going on?

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

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

发布评论

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

评论(2

太阳哥哥 2024-12-22 15:10:43

当您在 try 块中调用 Ptr f(path) 时,您正在创建一个名为 f 的全新变量,当您退出 try 块时,该变量将被销毁。

然后,在 try 块之外使用 f 的任何代码都将使用您在开始时创建的未初始化的 F。

我可以看到你有 2 个选项:

添加一个 Open 方法或类似于 Ptr 的方法,并从 try 块中调用它,或者将所有文件读取/写入代码包装在 try 块中,这样就可以避免返回 false ,因为抛出异常时所有代码都将被跳过。

选项 1:

Ptr f;
try
{
    f.Open( file );
}
catch
....

选项 2:

try
{
    Ptr f( file );
    f.read();
}
catch
.....

When you call Ptr f(path) in the try block, you're creating a whole new variable called f, that will be destroyed when you exit the try block.

Then any code that uses f outsidde the try block will be using the uninitialised F that you created at the start.

You have 2 options I can see:

Add an Open method or similar to Ptr and call that from within the try block, or perhaps wrap all your file reading/writing code in the try block, that way you can avoid the need for returning false, as all the code will have been skipped when an exception was thrown.

Option 1:

Ptr f;
try
{
    f.Open( file );
}
catch
....

Option 2:

try
{
    Ptr f( file );
    f.read();
}
catch
.....
暖心男生 2024-12-22 15:10:43

这可能是一个范围问题,请将其替换为:

bool getResult(const char* path) 
{
  try
  {
     Ptr f(path);
     char buf[1024];
     while (fgets(buf, sizeof(buf), f) == 0) 
     {
       if(errno == EINTR)
         continue;
       log.error("Error (%d) : %s",errno,path);
       return false;
     }
  ...
  } 
  catch(Exception& e) 
  {
    vlog.error("Could not open file at %s",path);
    return false;
  }
  return true;
}

its probably a scoping issue, replace it with:

bool getResult(const char* path) 
{
  try
  {
     Ptr f(path);
     char buf[1024];
     while (fgets(buf, sizeof(buf), f) == 0) 
     {
       if(errno == EINTR)
         continue;
       log.error("Error (%d) : %s",errno,path);
       return false;
     }
  ...
  } 
  catch(Exception& e) 
  {
    vlog.error("Could not open file at %s",path);
    return false;
  }
  return true;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文