简体   繁体   English

EXC_BAD_ACCESS - C++ substr 函数

[英]EXC_BAD_ACCESS - C++ substr function

I have a function that uses c++ substr.我有一个使用 c++ substr 的函数。 This function sometimes randomly crashes at the end of the program (when called from a separate thread) on Linux and macOS.在 Linux 和 macOS 上,此函数有时会在程序结束时(从单独的线程调用时)随机崩溃。

Here is the function:这是函数:

bool mkpath( string path )
{
bool bSuccess = false;
int nRC = ::mkdir( path.c_str(), 0775 );
if( nRC == -1 )
{
    switch( errno )
    {
        case ENOENT:
            //parent didn't exist, try to create it
            if( mkpath( path.substr(0, path.find_last_of('/')) ) )
            {
                //Now, try to create again.
                int status = ::mkdir( path.c_str(), 0775 );
                bSuccess = (0 == status || errno == EEXIST);
            }
            else
            {
                bSuccess = false;
            }
            break;
        case EEXIST:
            //Done!
            bSuccess = true;
            break;
        default:
            bSuccess = false;
            break;
    }
}
else
    bSuccess = true;
return bSuccess;
}

The lldb backtrace is as follows: lldb回溯如下:

* thread #4, stop reason = EXC_BAD_ACCESS (code=2, address=0x70000097fff8)
* frame #0: 0x00007fff73d2a81a libsystem_malloc.dylib`tiny_malloc_from_free_list + 8
frame #1: 0x00007fff73d2a297 libsystem_malloc.dylib`tiny_malloc_should_clear + 288
frame #2: 0x00007fff73d290c6 libsystem_malloc.dylib`szone_malloc_should_clear + 66
frame #3: 0x00007fff73d27d7a libsystem_malloc.dylib`malloc_zone_malloc + 104
frame #4: 0x00007fff73d27cf5 libsystem_malloc.dylib`malloc + 21
frame #5: 0x00007fff70ea0dea libc++abi.dylib`operator new(unsigned long) + 26
frame #6: 0x00007fff70e73d70 libc++.1.dylib`std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> 
>::basic_string(std::__1::basic_string<char, std::__1::char_traits<char>, 
std::__1::allocator<char> > const&, unsigned long, unsigned long, std::__1::allocator<char> 
const&) + 132
frame #7: 0x0000000103821467 libSampleLibrary.dylib`std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >::substr(unsigned long, unsigned 
long) const + 87
frame #8: 0x0000000103820c77 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 135
frame #9: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #10: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #11: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #12: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #13: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #14: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
frame #15: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144
...

Any possible reason why this could happen?这可能发生的任何可能原因? The thread from where this is called can be canceled from outside as we have added正如我们添加的那样,可以从外部取消调用 this 的线程

pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

at the first line in function from where this function gets called.在函数中调用此函数的第一行。

Whenever this crash occurs I see the following line in the backtrace more the 5400 times which is very surprising:每当发生此崩溃时,我都会在回溯中看到以下行超过 5400 次,这非常令人惊讶:

frame #15: 0x0000000103820c80 libSampleLibrary.dylib`mkpath(std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char> >) + 144

I further debugged and it turned out a static variable (homePath) gets corrupted (returns junk).我进一步调试,结果发现一个静态变量(homePath)被破坏(返回垃圾)。 The mkpath() function gets it value from the following function: mkpath() 函数从以下函数中获取它的值:

string GetSettingFilePath()
{
    static string homePath = "";
    if(!homePath.empty()){
        
        // sometimes homePath variable returns junk at the program exit
        return homePath;
    }

    struct passwd* pwd = getpwuid(getuid());

    if (pwd)
    {
        homePath = pwd->pw_dir;
    }
    else
    {
        // try the $HOME environment variable
        homePath = getenv("HOME");
    }
    if (homePath.empty())
    {
        homePath = "./";
    }
    return homePath
}

Since homePath variable returns junk sometimes at the program exit though it is set correctly, it caused infinite recursion.由于 homePath 变量虽然设置正确,但有时会在程序退出时返回垃圾,从而导致无限递归。 But why this static variable inside the function returns junk when called at the program exit.但是为什么函数内的这个静态变量在程序出口调用时会返回垃圾。

If you call mkpath recursively, and the string in path doesn't have a slash / .如果您递归调用mkpath ,并且path的字符串没有斜杠/ then you will have infinite recursion.那么你将有无限递归。

The recursion will be infinite as you will call mkpath with the exact same argument it was already called with.递归将是无限的,因为您将mkpath与它已经调用的完全相同的参数调用mkpath

You should check if path really have a slash / before doing the recursive call.在进行递归调用之前,您应该检查path真的有斜杠/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM