Segfault 使用 bool 类型的向量

Posted

技术标签:

【中文标题】Segfault 使用 bool 类型的向量【英文标题】:Segfault working with vectors of type bool 【发布时间】:2012-06-25 18:56:23 【问题描述】:

我正在尝试解决一个编程难题并遇到一些困难。它类似于Project Euler problem 215,但块的宽度为 3 和 4.5。无论如何,我最初是通过暴力强制 C 中的组合来接近它,但我试图通过计算第一行中的所有组合并查看有多少有效方式来组合它们然后从那里开始来加快运行时间。我认为使用布尔向量(尝试过的位集,但我不能使用它们,因为我在编译时没有可用的宽度)会更容易,但我没有使用向量的经验我做了一些事情让段错误之神生气。我只是看不到在哪里。

当我输入程序参数时,我遇到了分段错误 11,所以这绝对是我所做的,当我在 GDB 中运行回溯时,我得到以下信息:

#0  0x0000000100002645 in std::_Bit_reference::operator= ()
#1  0x0000000100001be2 in build ()
#2  0x0000000100002287 in main ()

我知道肯定有一些我没有看到的东西。只有在实际调用 build() 时才会发生这种情况,但我将 main() 包括在内,以防万一我可能在调用中做错了什么。

#include <vector>

void build(std::vector<std::vector<bool> > possibilities, std::vector<bool> current, float width)

if(current.size() > 0)

    if(current.size() > width) return; // If we went over the specified width, bail out-invalid

    if (current.size() == width) // If we just matched the width for this row, push it on to our vector of possibilities
    
        possibilities.push_back(current);
        return;
    


// Try adding a block of length 3 and a block of length 4.5
std::vector<bool> branch1;
std::vector<bool> branch2;
if(current.size() > 0)

    branch1.assign( current.begin(), current.end() );
    branch2.assign( current.begin(), current.end() );

    branch1[ current.size() + 5 ] = 1;
    branch2[ current.size() + 8 ] = 1;

else

    branch1[5] = 1;
    branch2[8] = 1;

// Split off and check both branches
build(possibilities, branch1, width);
build(possibilities, branch2, width);


int main( int argc, char *argv[] )

if ( argc == 3 ) // Number of arguments should be 3-the program name, plus our width and height

    float width = (atof(argv[1]) * 2); // Width is assumed to be entered first, converting to integer
    int height = atoi(argv[2]); // The second argument should be height, ditto above
    if ( (width < 3) || (height < 1) ) // Catches non-number inputs (atof/i returns 0) and invalid entries
    
        printf("Expected two numeric arguments, width and height, in that order.");
    
    else // Continue the program
    
        std::vector<bool> noo;
        std::vector<std::vector<bool> > possibilities;
        build(possibilities, noo, width);
        printf("%llu", (unsigned long long)possibilities.size());
    

else

    printf("Expected two numeric arguments, width and height, in that order.");


【问题讨论】:

如果将它们更改为std::vector&lt;int&gt;,是否可以避免segfaultC++03 中的 vector of bool 是一种奇怪的野兽,因为根据标准,它甚至不是有效的 Sequence。幸运的是,这在 C++11 中被恢复了。 std::vector 在默认构造时最初的大小为0。您正在尝试访问您的 build() 函数的 else 语句中根本不存在的元素。不确定您要完成什么,因为您的问题并不能立即明确。 有趣 - 您在递归函数中按值传递参数。是设计使然吗? @K-ballo,vector&lt;bool&gt; 在 C++11 中是如何修改的?我找不到参考资料。 @Mark Ransom:快速阅读标准,似乎vector&lt;bool&gt; 仍然作为非序列 :( 【参考方案1】:

您的noo 向量:

std::vector<bool> noo;

build的第二个参数是什么:

build(possibilities, noo, width);

是空的。但是,在 build 内部,您会根据该向量的大小执行一些操作:

std::vector<bool> branch1;
std::vector<bool> branch2;
if(current.size() > 0) //current is actually noo

    branch1.assign( current.begin(), current.end() );
    branch2.assign( current.begin(), current.end() );

    branch1[ current.size() + 5 ] = 1;
    branch2[ current.size() + 8 ] = 1;

else

    branch1[5] = 1;
    branch2[8] = 1;

由于它是空的,您将访问向量branch1branch2(也是空的)的位置58,从而导致未定义的行为。

您应该以某种方式调整 branch1branch2 的大小,以免执行越界访问。

这边:

std::vector<bool> branch1(someNumber);

会做,但你应该看看你的代码的逻辑,肯定还有其他问题。此外,您正在按值传递参数,因此您正在制作不必要的副本,并且您不会看到从 mainpossibilities 向量所做的修改。

【讨论】:

@Chad 否。如果 OP 使用 std::vector::at 访问向量,则会引发异常。由于他使用的是operator[](不执行访问检查),这肯定是未定义的行为。 你是对的,at() 成员函数提供了范围检查,而operator[]没有

以上是关于Segfault 使用 bool 类型的向量的主要内容,如果未能解决你的问题,请参考以下文章

使用向量和 fstream 的代码中的 Segfault 11? C++

LibSVM 在大特征向量上失败 (SEGFAULT)

带有指向向量的向量的 Segfault

返回包含向量的空向量时的C++ Segfault

Seg Fault 创建新的 QTcpSocket

创建 avx 向量时的 Segfault