【问题标题】:Error with threads opening files线程打开文件时出错
【发布时间】:2010-02-28 03:26:10
【问题描述】:

我在 Linux 机器上使用 C 和 pthread,但我无法并行化程序。

我基本上是在尝试获取一个数据文件文件夹,将它们分成组,每个组由一个线程处理,并在每个数据文件上运行一个函数。

我这样做的方式是我有一个全局 char **filename 变量,其中 filename[i] = 数据文件的文件名。在主函数中,我将使用 scandir 读取所有数据文件的文件名(减去“.”和“..”)并将它们放入文件名变量中。然后创建 4 个(任意数)线程,每个线程调用 Process 函数。在 Process() 中,每个线程仅打开(使用在 Process() 中声明的 FILE *fin)并使用 start_index 和 end_index 处理部分数据文件。例如,如果有 100 个文件,那么每个线程将分别处理 filename[0]filename[24]filename[25]filename[49]filename[50]filename[74]filename[75]filename[99]。完成后,main() 中有一个 pthread_join 用于所有 4 个线程。

我已检查文件名是否已正确存储在 main() 和 Process() 中。但是,我在 Process() 中不断遇到分段错误:

for (i = start_index; i <= end_index ; i++)
   fin = fopen(filename[i], "rb"); <--- Seg fault

我真的不明白为什么会出现错误,因为没有线程试图打开同一个文件。

请指教。

【问题讨论】:

  • 请贴出创建文件数组的代码...
  • 您是否尝试过在 gdb 中运行它并查看 i 在出现段错误时是什么?
  • 还有,当出现段错误时,filename[i] 是什么?
  • scandir 返回非4 的倍数时,请注意舍入错误和超出文件名[] 数组最多3 个插槽。此外,您是否正确传输了来自scandir 的所有文件名指针' s namelist 并且在所有工作线程完成之前未释放 namelist 的成员?
  • 先试试单线程的代码。它也有段错误吗?

标签: c linux pthreads


【解决方案1】:

我在这里猜测,您可能将filename[i] 设置为namelist[i]-&gt;d_name,然后在namelist[i] 上调用free(3)。在此之后,指向文件名的指针无效。或者free(3) 发生在主线程中并与处理线程竞争。你真的需要strdup(3)每个字符串,只有在你真正完成后才释放内存。

我当然可能是错的,因为给出的代码没有显示字符串是如何分配的。

【讨论】:

    【解决方案2】:

    发生崩溃时start_indexend_index 的值是多少,因此i 的值是多少?

    如果i 受到控制,代码不应崩溃 - 这是我要检查的第一件事。

    显示代码片段可恶地泄漏文件流,因为它在每次迭代时都会覆盖fin。我认为这是将测试代码减少到最低限度的人工制品,而不是(尚未)工作程序的实际行为。

    【讨论】:

    • 一个进程可以拥有的文件句柄数量有软硬限制,在大多数 Linux 系统上通常为 1024。确保您没有使用更多。 ulimit 将显示单个进程可以拥有的允许文件数。如果您打开的文件数量超过允许的文件数量,则会更改限制,它应该可以工作。
    【解决方案3】:

    这与线程无关。

    线程是否在分配文件名之前执行代码?你的索引正确吗?如果文件名来自scandir ...您是复制文件名还是仅指向scandir返回的值...因为该值不是长期的。您是否将 filename[i] 指向调用 scandir 的函数堆栈上的字符串?

    尝试使用 strdup 设置文件名[i],看看是否可行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-08
      • 2016-07-13
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多