質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

6530閲覧

segmentation faultの解決

yasazz555

総合スコア10

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/09/08 05:19

前提・実現したいこと

プログラムを実行するとsegmentation faultのエラーが発生するのですが、どうすれば直るのかわかりません。助けてください。

発生している問題・エラーメッセージ

windows10 + wsl2 + ubuntu
vscodeの拡張機能のcmakeでコンパイルしている。
vscodeの機能でデバッグすると
下の該当コードのfor (int index : P_to_index[b.first][b.second])の部分で

Segmentation fault

が起きています。
一行ずつデバッグしていくとSegmentation faultの位置が毎回変わります。

gdbで実行すると

Thread 1 "main" received signal SIGSEGV, Segmentation fault. 0x00005555555f4d1f in __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<std::pair<int, int> const, int>, true> >::construct<std::pair<std::pair<int, int> const, int>, std::pair<std::pair<int, int> const, int> const&> (this=0x7fffffffdae0, __p=0x5555577aba98) at /usr/include/c++/9/ext/new_allocator.h:147 147 { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

とでました。

該当のソースコード

実際にエラーが出ているコードそのものではないですが、似たようなコードを書いてみました。
コードの大まかな内容は、与えられたビットデータの1の数が多い順に選ぶというものです。

c++

1#include <bit> 2#include <boost/functional/hash.hpp> 3#include <iostream> 4#include <unordered_map> 5#include <unordered_set> 6#include <vector> 7 8using namespace std; 9using P = pair<int, int>; 10 11vector<vector<unordered_set<int>>> P_to_index; 12struct A { 13 unordered_map<P, int, boost::hash<P>> num; 14 vector<vector<uint64_t>> bit_data; 15 int count; // bit_dataの1の数の合計値 16}; 17vector<A> a; 18void a_function(); 19int main() { 20 a_function(); // aの中身を作る 21 unordered_set<int> selected_a; 22 while (1) { 23 int max_count = 0; 24 int max_index; 25 // count数が最大のaを選択 26 for (int i = 0; i < a.size(); i++) { 27 if (max_count < a[i].count) { 28 max_count = a[i].count; 29 max_index = i; 30 } 31 } 32 if (max_count == 0) break; 33 selected_a.insert(max_index); 34 a[max_index].count = 0; 35 auto& max_a = a[max_index]; 36 for (auto [b, c] : max_a.num) { 37 for (int index : P_to_index[b.first][b.second]) { 38 if (selected_a.count(index)) continue; 39 int cnt = 0; 40 int bit_idx = a[index].num[b]; 41 for (int bi = 0; bi < 500; bi++) { 42 uint64_t bit = 43 a[index].bit_data[bit_idx][bi] & max_a.bit_data[c][bi]; 44 cnt += __popcount(bit); 45 max_a.bit_data[c][bi] ^= bit; 46 } 47 a[index].count -= cnt; 48 } 49 } 50 } 51 for (int i : selected_a) { 52 cout << i << '\n'; 53 } 54 return 0; 55}

new_allocator.hの中身も載せておきます。

c

1// Allocator that wraps operator new -*- C++ -*- 2 3// Copyright (C) 2001-2019 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 3, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// Under Section 7 of GPL version 3, you are granted additional 17// permissions described in the GCC Runtime Library Exception, version 18// 3.1, as published by the Free Software Foundation. 19 20// You should have received a copy of the GNU General Public License and 21// a copy of the GCC Runtime Library Exception along with this program; 22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23// <http://www.gnu.org/licenses/>. 24 25/** @file ext/new_allocator.h 26 * This file is a GNU extension to the Standard C++ Library. 27 */ 28 29#ifndef _NEW_ALLOCATOR_H 30#define _NEW_ALLOCATOR_H 1 31 32#include <bits/c++config.h> 33#include <new> 34#include <bits/functexcept.h> 35#include <bits/move.h> 36#if __cplusplus >= 201103L 37#include <type_traits> 38#endif 39 40namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 41{ 42_GLIBCXX_BEGIN_NAMESPACE_VERSION 43 44 using std::size_t; 45 using std::ptrdiff_t; 46 47 /** 48 * @brief An allocator that uses global new, as per [20.4]. 49 * @ingroup allocators 50 * 51 * This is precisely the allocator defined in the C++ Standard. 52 * - all allocation calls operator new 53 * - all deallocation calls operator delete 54 * 55 * @tparam _Tp Type of allocated object. 56 */ 57 template<typename _Tp> 58 class new_allocator 59 { 60 public: 61 typedef size_t size_type; 62 typedef ptrdiff_t difference_type; 63 typedef _Tp* pointer; 64 typedef const _Tp* const_pointer; 65 typedef _Tp& reference; 66 typedef const _Tp& const_reference; 67 typedef _Tp value_type; 68 69 template<typename _Tp1> 70 struct rebind 71 { typedef new_allocator<_Tp1> other; }; 72 73#if __cplusplus >= 201103L 74 // _GLIBCXX_RESOLVE_LIB_DEFECTS 75 // 2103. propagate_on_container_move_assignment 76 typedef std::true_type propagate_on_container_move_assignment; 77#endif 78 79 _GLIBCXX20_CONSTEXPR 80 new_allocator() _GLIBCXX_USE_NOEXCEPT { } 81 82 _GLIBCXX20_CONSTEXPR 83 new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { } 84 85 template<typename _Tp1> 86 _GLIBCXX20_CONSTEXPR 87 new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } 88 89 ~new_allocator() _GLIBCXX_USE_NOEXCEPT { } 90 91 pointer 92 address(reference __x) const _GLIBCXX_NOEXCEPT 93 { return std::__addressof(__x); } 94 95 const_pointer 96 address(const_reference __x) const _GLIBCXX_NOEXCEPT 97 { return std::__addressof(__x); } 98 99 // NB: __n is permitted to be 0. The C++ standard says nothing 100 // about what the return value is when __n == 0. 101 _GLIBCXX_NODISCARD pointer 102 allocate(size_type __n, const void* = static_cast<const void*>(0)) 103 { 104 if (__n > this->max_size()) 105 std::__throw_bad_alloc(); 106 107#if __cpp_aligned_new 108 if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) 109 { 110 std::align_val_t __al = std::align_val_t(alignof(_Tp)); 111 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al)); 112 } 113#endif 114 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); 115 } 116 117 // __p is not permitted to be a null pointer. 118 void 119 deallocate(pointer __p, size_type) 120 { 121#if __cpp_aligned_new 122 if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) 123 { 124 ::operator delete(__p, std::align_val_t(alignof(_Tp))); 125 return; 126 } 127#endif 128 ::operator delete(__p); 129 } 130 131 size_type 132 max_size() const _GLIBCXX_USE_NOEXCEPT 133 { 134#if __PTRDIFF_MAX__ < __SIZE_MAX__ 135 return size_t(__PTRDIFF_MAX__) / sizeof(_Tp); 136#else 137 return size_t(-1) / sizeof(_Tp); 138#endif 139 } 140 141#if __cplusplus >= 201103L 142 template<typename _Up, typename... _Args> 143 void 144 construct(_Up* __p, _Args&&... __args) 145 noexcept(noexcept(::new((void *)__p) 146 _Up(std::forward<_Args>(__args)...))) 147 { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } 148 149 template<typename _Up> 150 void 151 destroy(_Up* __p) 152 noexcept(noexcept( __p->~_Up())) 153 { __p->~_Up(); } 154#else 155 // _GLIBCXX_RESOLVE_LIB_DEFECTS 156 // 402. wrong new expression in [some_] allocator::construct 157 void 158 construct(pointer __p, const _Tp& __val) 159 { ::new((void *)__p) _Tp(__val); } 160 161 void 162 destroy(pointer __p) { __p->~_Tp(); } 163#endif 164 165 template<typename _Up> 166 friend bool 167 operator==(const new_allocator&, const new_allocator<_Up>&) 168 _GLIBCXX_NOTHROW 169 { return true; } 170 171 template<typename _Up> 172 friend bool 173 operator!=(const new_allocator&, const new_allocator<_Up>&) 174 _GLIBCXX_NOTHROW 175 { return false; } 176 }; 177 178_GLIBCXX_END_NAMESPACE_VERSION 179} // namespace 180 181#endif 182

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

c++

1for (int bi = 0; bi < 500; bi++) { 2 uint64_t bit = 3 a[index].bit_data[bit_idx][bi] & max_a.bit_data[c][bi]; 4 cnt += __popcount(bit); 5 max_a.bit_data[c][bi] ^= bit; 6 }

ここの部分のa[index].bit_data[bit_idx][bi]のbiの部分に範囲外アクセスがありました。
全て500個ではなかったので修正すると直りました。
あまりよくわかりませんが、範囲外の部分に代入することでaのvector全体に不具合が起こって、aを参照する別の部分でsegmentation faultが起こってました。
printfの有無でもsegmentaion faultの場所が変わるので、printfで処理部分を挟み込んで特定しようとすると、すり抜けたりして苦しんだりしました。

投稿2021/09/09 14:12

yasazz555

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

最終的な解決につながるか分かりませんが…

C++

1for (int index : P_to_index[b.first][b.second]) {

の行が怪しそうです。提示されているコードでは、P_to_indexが初期化後に更新されておらず、0行0列の二次元配列になっていますが、添え字がアクセス可能な範囲にあることは、保証されていますか?

投稿2021/09/08 14:08

majiponi

総合スコア1722

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yasazz555

2021/09/08 14:58

回答ありがとうございます。 説明が足りなかったですが、 a_function()の部分でP_to_indexを更新しています。 vectorの部分は最初にresizeで大きさを指定して、unordered_setの部分は適宜insertするということをしていました。 for (int bi = 0; bi < 500; bi++)の部分はループが500回ですが、1回にしたりすると、segmentation faultが起きなかったりします。 アクセス可能範囲にあると思うのですが、絶対とは言い切れないのでまた入念に調べたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問