【问题标题】:C++ Renaming Files with Qt causes SIGSEGVC++ 使用 Qt 重命名文件会导致 SIGSEGV
【发布时间】:2013-10-18 13:42:00
【问题描述】:

我刚刚使用一个名为“Sound Juicer”的程序将我所有的 CD 复制到了我的计算机上。它工作正常,它为每个艺术家创建一个文件夹,并为每个专辑创建另一个文件夹。当然,在这些文件夹中还有 mp3 文件。

问题是我想要曲目编号、艺术家和曲目标题作为我歌曲的名称。 Sound Juicer 所做的是在代表“Disk 1 Title”的文件前面添加 d1t。

我是一名程序员,所以我用这个问题来练习一下。这有效:

void MainWindow::rename( const QString & text )
{
    static int _files = 0;

    QDir dir( text );
    QFileInfoList a = dir.entryInfoList( QDir::Files | QDir::Dirs );
    for( int i = 2; i < a.size(); i++ )
    {
        static QDir tmp;

        if( a.at( i ).isDir() )
            rename( a.at( i ).absoluteFilePath() );

        if( a.at( i ).fileName().startsWith( "d1t" ) || a.at( i ).fileName().startsWith( "d2t" ) )
        {
            QString newFile = a.at( i ).fileName().remove(0,3);
            tmp = a.at( i ).dir();

            if( !tmp.rename( a.at( i ).fileName(), newFile ) )
                qDebug() << "Failed";

            _files++;
        }
    }
}

它检查一个目录,选择第一个文件或目录并检查它是什么。如果它是一个目录,它会调用自己(递归)并重新开始,直到他找到一些文件或不再存在目录。如果找到一个文件,它会重命名它并将文件计数器加 1。

然而,它只重命名了前 2 或 3 个目录中的所有文件。之后,它引起了 SIGSEGV。有谁知道怎么回事?

我的目录示例:

1 个目录(“Sum 41”)-> 1 个子目录(“All Killer No Filler”)-> 文件“d1t01.Sum 41 - Introduction to Destruction.mp3”等...... 2 子目录(“Blah Blah”)-> 文件 ...

2 个目录(“Shinedown”)-> 1 个子目录(“疯狂之声”)-> 文件 d1t01。 Shinedown - Devour.mp3 等...

3 目录(“Guns N' Roses”)-> 子目录(“Blah Blah”)-> 文件 ... 子目录(“Blah”)-> 文件 ...

【问题讨论】:

  • 在调试器中运行它,看看它在哪里崩溃。
  • @FrankOsterfeld 在这里崩溃: QFileInfoList a = dir.entryInfoList( QDir::Files | QDir::Dirs );我试着让列表的寿命更长,当它超出范围时它会被销毁,对吧?
  • 尝试去除静电,看看会发生什么。
  • @fonZ 现在它会在一段时间后崩溃。我的 Guns n' Roses 文件仍然没有变化
  • 检查堆栈溢出或无限递归(可能由符号链接引起)另外,使用 QDir::NoDotAndDotDot 和 i = 0 比 i = 2 更好; ...

标签: c++ qt directory


【解决方案1】:

使用 static 你试图告诉编译器你只想要整个程序中的一个实例,但你把它放在一个 for 循环中。那不是很干净。在这种情况下,静态是无用的。由于静态初始化混乱问题,静态也会导致问题。因此,如果您真的不需要静态初始化,请将其删除并使其成为局部变量或类变量。

重写您的方法,以便更好地阅读它,我看到您递归调用该方法,这可能会导致无限循环。

另一个问题是你的文件变量,它的目的是什么?

void MainWindow::rename( const QString & text ) {
    int files = 0;

    QDir dir(text); // does QDir also accept wrong paths?
    QFileInfoList list = dir.entryInfoList(QDir::Files|QDir::Dirs); // does it return a list in all cases?
    foreach (QFileInfo entry, list) {
        if (entry.isDir()) {
            //is everything always ok when doing this?
            // POTENTIAL infinite loop 
            rename(entry.absoluteFilePath());
        }
        else {
            QString fileName = entry.fileName();
            if(fileName.startsWith("d1t") || fileName.startsWith("d2t")) {
                if (!entry.dir().rename(fileName, fileName.remove(0,3))) qDebug() << "Failed";
                files++;
            }
        }
    }
}

【讨论】:

  • @Davlog 是的,但你在哪里使用它?如果在同一个类中使用,则声明为类变量。
  • 好吧,这是有道理的。此外 (QDir::Files|QDir::Dirs) 不是必需的。我又把它删了。结果相同
  • @Davlog 使用调试器查看程序崩溃的位置,因为这样很难判断。
  • QFileInfoList a = dir.entryInfoList(QDir::Files | QDir::Dirs);
  • 错误是什么?我会检查 dir 是否有效以及它指向的目录。只是猜测您可能没有该目录所需的权限。
【解决方案2】:

我在 fonZ 和 Frank Osterfeld 的帮助下以某种方式修复了它。我终于创建了一个 GUI 来选择一条路径。不过,我已经做到了。这段代码查找所有目录而不会导致无限循环或溢出(到目前为止)。问题在于 QDir 和 QFileInfo 获取路径的函数。我玩了一会儿,结果出来了:

void MainWindow::rename( const QString& path )
{
    //If invalid path return
    if( path.isEmpty() || ( !QDir( path ).exists() ) )
        return;

    //entryInfoList( QDir::NoDotAndDotDot ) doesn't work. 
    QFileInfoList fileList = QDir( path ).entryInfoList();

    foreach (QFileInfo entry, fileList ) {

        //Eliminating wrong paths
        if( entry.isDir() ){
            if( entry.filePath().endsWith(".") )
                continue;

            //Start function again with new directory
            rename( entry.filePath() );
        }
        else{

            QString fileName = entry.fileName();
            if( fileName.startsWith( "d1t" ) || fileName.startsWith( "d2t" ) ){
                //Remove those characters
                fileName.remove( 0, 3 );

                //If renaming is successful, increment the successful files
                //If not, increment the failed files and print an error
                if( entry.dir().rename( entry.fileName(), fileName ) )
                    files++;
                else{
                    addError( "Could not rename " + entry.fileName() + " to " + fileName );
                    filesFailed++;
                }

            }
        }

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    • 2012-11-28
    • 2019-08-17
    • 1970-01-01
    • 2014-05-24
    • 2017-07-09
    • 1970-01-01
    相关资源
    最近更新 更多