const std::string::size() 比优化级别 2 中应有的要大得多

const std::string::size() is much larger than it should be in optimization level 2

提问人:Jie Feng 提问时间:6/27/2023 最后编辑:Jie Feng 更新时间:7/3/2023 访问量:64

问:

定义:

const std::string a_class::dft_col_name{"NONE"};

用法:

在 a_class::function() 中

只要循环一次,我是 0

for (int i = 0; i < result->colnum; ++i) {
    result->pcolname[(i + 1) * SQLCOLLEN - 1] = '\0';
    auto colname_len = strlen(result->pcolname + i * SQLCOLLEN);
    if (colname_len == 0) {
        // given column name if there isn't
        strcpy(result->pcolname + i * SQLCOLLEN, dft_col_name.c_str());
        colname_len = dft_col_name.size();

        /*!! Confusion !!*/

        std::cout << dft_col_name << '\n';
        // O2 print: lots of corrupted text
        std::cout << dft_col_name.c_str() << '\n';
        // O2 print: "NONE"
        printf("%lu %lu %s\n", colname_len, dft_col_name.size(), dft_col_name.c_str());
        // -g O0 print: 4 4 NONE
        // O2 print: 17179869184 17179869184 NONE

    }
    result->plen[i] = colname_len;
}

一些调试信息复制为:

66                  std::cout << dft_col_name.size() << '\n';
(gdb) 
17179869184
67                  colname_len = dft_col_name.size();
(gdb) p dft_col_name 
$1 = ""
(gdb) p dft_col_name .size()
$2 = 4
(gdb) p dft_col_name.c_str()
$3 = 0x659c98 "NONE"

什么:result

struct ResultInfo{
...
int16_t colnum; // SQL result column number. It's 1 in this problem.
...
int16_t* pcolname; // SQL result columns' name. Each has SQLCOLEN characters.
...
};

#define SQLCOLEN 64

它是从网络反序列化的,在内存中它看起来像:

| struct ResultInfo | <pcolname point to here> colnum * 64 char |

环境:

Linux version 3.10.0-1062.12.1.el7.x86_64 ([email protected])
(gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Tue Feb 4 23:02:59 UTC 2020

g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

我真的很困惑!

我尝试使用调试,但没有找到。valgrind --tool=memcheckInvalid write

我试着把 、 和 重新绑在一起,它起作用了。const std::stringconst char[]dft_col_name.size()strlen()

我尝试从类成员中删除 作为 中的全局变量 ,或 中的局部变量。它没有用。static const std::string a_class::dft_col_nameconst std::string dft_col_name.cppa_class::function()

C++11 编译 stdstring

评论

0赞 Jie Feng 6/27/2023
我用选项在优化级别 1 中编译它,然后是它。变量为-ggdbdft_col_namevalue has been optimized out
0赞 Retired Ninja 6/27/2023
你能把一个最小的可重复的例子放在一起吗?了解什么是和是什么会有所帮助。看起来你肯定在某个地方破坏了内存。resultSQLCOLLEN
0赞 user17732522 6/27/2023
另一个常见问题:在初始化全局静态对象期间使用,但尚不能保证初始化完成。a_class::function()a_class::dft_col_name
0赞 Jie Feng 6/27/2023
很难提供一个最小的可重复示例,因为它是一个复杂的系统。我在上面添加描述。result
1赞 user17732522 6/27/2023
你在某处写出界外的东西。除了 valgrind,您还可以尝试 ASAN 来检测它。我认为所提供的信息不能说更多。

答:

0赞 Jie Feng 6/28/2023 #1

没有更多的时间解决这个问题。暂时更换为作品。const std::stringconst char[]

经过几天的努力,我们发现其中一个标题中有,但没有!!#pragma pack(push, 1)#pragma pack(pop)