【发布时间】:2023-01-12 03:39:18
【问题描述】:
下面的 Linux 程序通过向文件系统路径添加一些字符串来构建路径:
#include <filesystem>
int main(int, char**) {
//
std::cout << "Application STARTING\n";
//
fs::path path;
// Add to path
path /= "/media";
path /= "aaa";
path /= "bbb";
// path /= "ccc";
//
std::cout << path.c_str() << std::endl;
//
std::cout << "Application STOPPED\n";
}
如果我在 valgrind 中运行这个文件,这是输出:
Application STARTING
/media/aaa/bbb
Application STOPPED
如果我取消注释将“ccc”添加到路径的行,编译并在 valgrind 中再次运行,我得到:
Application STARTING
==2231== Invalid read of size 1
==2231== at 0x4860214: ??? (in /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so)
==2231== Address 0x4d25c17 is 0 bytes after a block of size 31 alloc'd
==2231== at 0x4848744: operator new(unsigned int) (vg_replace_malloc.c:282)
==2231== by 0x4A79CBB: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned int, unsigned int, char const*, unsigned int) (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.28)
==2231==
/media/aaa/bbb/ccc
Application STOPPED
我正在使用这些设置进行编译:
/usr/bin/arm-linux-gnueabihf-g++ -I/usr/include/alsa -pthread -Wall -Wextra -pedantic -g -DTMTP_DEBUG -std=gnu++17 -o CMakeFiles/tmtp.dir/main.cpp.o -c /media/ssd/projects/tmtp/code/main.cpp
这是一个 valgrind 错误吗?我是否正确使用了 fs::path?
_ 更新 _
我已经减少到最低编译器设置:
/usr/bin/arm-linux-gnueabihf-g++ -g -std=gnu++17 -o CMakeFiles/tmtp.dir/main.cpp.o -c /media/ssd/projects/tmtp/code/main.cpp
我在 C++17 中编译,因为这允许我使用文件系统的非实验版本。
仍然报告错误的内存读取。
_ 另一个更新 _
我可以在不使用文件系统的情况下创建无效读取错误。下面的代码也报告无效读取。代码中标记了两行,注释掉其中任何一行都可以删除无效读取。
#include <iostream>
#include <string.h>
class CPath
{
public:
inline const char* c_str() const { return m_strPath.c_str(); }
inline void operator/=(const char* psz) { append(psz); }
public:
void append(const char* psz)
{
//
m_strPath += '/'; // <--- REMOVE TO PREVENT INVALID READ
m_strPath.append(psz);
}
private:
std::string m_strPath;
};
int main(int, char**) {
//
std::cout << "Application STARTING\n";
//
CPath path;
path /= "media";
path /= "aaa";
path /= "bbb";
path /= "ccc"; // <--- REMOVE TO PREVENT INVALID READ
//
std::cout << path.c_str() << std::endl;
//
std::cout << "Application STOPPED\n";
}
【问题讨论】:
-
此处显示的代码没有任何问题。因此,问题一定出在此处显然未显示且被排除在外的代码。这就是错误所在。不幸的是,任何人都不可能找出甚至没有显示的代码的问题。仅仅因为程序在这里崩溃并不意味着问题就出在这里。 C++ 不是这样工作的。该错误可能出现在任何地方,但它不会立即崩溃,程序会运行一段时间,然后最终在随机代码行崩溃。
-
听起来像是您正在使用的标准 C++ 库的错误。
-
尝试添加这样一行: char* p = new char[8];我怀疑你会得到一个错误。
-
KonstantinL:你是对的。我现在有两个无效读取,我也不知道是什么原因造成的。
-
@Richard,您似乎正在编译禁止动态内存分配的嵌入式软件。
标签: c++ linux valgrind string.h